Add kde patches
The nixpkgs patch is to clear out a conflict with a patch that's applied to plasma-workspace by nixpkgs
This commit is contained in:
parent
fd0f27145a
commit
98f9b3a8fc
23 changed files with 7818 additions and 0 deletions
2
roles/kde/patches/bluedevil/patches.txt
Normal file
2
roles/kde/patches/bluedevil/patches.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Plasma 6.5.0:
|
||||
Pr 218 https://invent.kde.org/plasma/bluedevil/-/merge_requests/218
|
||||
53
roles/kde/patches/bluedevil/pr218.patch
Normal file
53
roles/kde/patches/bluedevil/pr218.patch
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
From ddbf7452c6f2fe8849de723175710dbf39242422 Mon Sep 17 00:00:00 2001
|
||||
From: Nate Graham <nate@kde.org>
|
||||
Date: Fri, 13 Jun 2025 11:55:47 -0600
|
||||
Subject: [PATCH] applet: use standard section headers
|
||||
|
||||
We have them; might as well use them. This lets us get rid of a bunch of
|
||||
complex and fragile code that's responsible for the existing separator.
|
||||
---
|
||||
.../contents/ui/FullRepresentation.qml | 27 +++----------------
|
||||
1 file changed, 3 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/applet/package/contents/ui/FullRepresentation.qml b/src/applet/package/contents/ui/FullRepresentation.qml
|
||||
index df989267d..27295de21 100644
|
||||
--- a/src/applet/package/contents/ui/FullRepresentation.qml
|
||||
+++ b/src/applet/package/contents/ui/FullRepresentation.qml
|
||||
@@ -111,31 +111,10 @@ PlasmaExtras.Representation {
|
||||
bottomMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
section.property: "Section"
|
||||
- // We want to hide the section delegate for the "Connected"
|
||||
- // group because it's unnecessary; all we want to do here is
|
||||
- // separate the connected devices from the available ones
|
||||
- section.delegate: Loader {
|
||||
+ section.delegate: PlasmaExtras.ListSectionHeader {
|
||||
required property string section
|
||||
-
|
||||
- active: section !== "Connected" && BluezQt.Manager.connectedDevices.length > 0
|
||||
-
|
||||
- width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin
|
||||
- // Need to manually set the height or else the loader takes up
|
||||
- // space after the first time it unloads a previously-loaded item
|
||||
- height: active ? Kirigami.Units.gridUnit : 0
|
||||
-
|
||||
- // give us 2 frames to try and figure out a layout, this reduces jumpyness quite a bit but doesn't
|
||||
- // entirely eliminate it https://bugs.kde.org/show_bug.cgi?id=438610
|
||||
- Behavior on height { PropertyAnimation { duration: 32 } }
|
||||
-
|
||||
- sourceComponent: Item {
|
||||
- KSvg.SvgItem {
|
||||
- width: parent.width - Kirigami.Units.gridUnit * 2
|
||||
- anchors.centerIn: parent
|
||||
- imagePath: "widgets/line"
|
||||
- elementId: "horizontal-line"
|
||||
- }
|
||||
- }
|
||||
+ width: listView.width - listView.leftMargin - listView.rightMargin
|
||||
+ text: section
|
||||
}
|
||||
highlight: PlasmaExtras.Highlight {}
|
||||
highlightMoveDuration: Kirigami.Units.shortDuration
|
||||
--
|
||||
GitLab
|
||||
|
||||
2
roles/kde/patches/breeze/patches.txt
Normal file
2
roles/kde/patches/breeze/patches.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Plasma 6.5.0:
|
||||
Pr 545 https://invent.kde.org/plasma/breeze/-/merge_requests/545
|
||||
333
roles/kde/patches/breeze/pr545.patch
Normal file
333
roles/kde/patches/breeze/pr545.patch
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
From 38567c2f2d2d0f8524e42224dff53a929cbf086a Mon Sep 17 00:00:00 2001
|
||||
From: Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
Date: Sat, 24 May 2025 09:33:44 +0200
|
||||
Subject: [PATCH 1/3] kstyle/animations: Use QObject as base type rather than
|
||||
QWidget
|
||||
|
||||
This prepares for the animation engine being used with Qt Quick Controls.
|
||||
|
||||
In most cases the type is cast to the relevant widget type for checking
|
||||
anyway, so might as well use the cast object further down but not require
|
||||
a QWidget at the beginning.
|
||||
---
|
||||
kstyle/animations/breezeanimations.cpp | 48 +++++++++++++-------------
|
||||
kstyle/animations/breezeanimations.h | 4 +--
|
||||
2 files changed, 26 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp
|
||||
index 12e5107c5..ceab53802 100644
|
||||
--- a/kstyle/animations/breezeanimations.cpp
|
||||
+++ b/kstyle/animations/breezeanimations.cpp
|
||||
@@ -82,7 +82,7 @@ void Animations::setupEngines()
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
-void Animations::registerWidget(QWidget *widget) const
|
||||
+void Animations::registerWidget(QObject *widget) const
|
||||
{
|
||||
if (!widget) {
|
||||
return;
|
||||
@@ -101,37 +101,37 @@ void Animations::registerWidget(QWidget *widget) const
|
||||
// for optimization, one should put with most used widgets here first
|
||||
|
||||
// buttons
|
||||
- if (qobject_cast<QToolButton *>(widget)) {
|
||||
- _toolButtonEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ if (auto toolButton = qobject_cast<QToolButton *>(widget)) {
|
||||
+ _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus);
|
||||
+ _widgetStateEngine->registerWidget(toolButton, AnimationHover | AnimationFocus);
|
||||
|
||||
} else if (qobject_cast<QCheckBox *>(widget) || qobject_cast<QRadioButton *>(widget)) {
|
||||
_widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed);
|
||||
|
||||
- } else if (qobject_cast<QAbstractButton *>(widget)) {
|
||||
+ } else if (auto button = qobject_cast<QAbstractButton *>(widget)) {
|
||||
// register to toolbox engine if needed
|
||||
- if (qobject_cast<QToolBox *>(widget->parent())) {
|
||||
- _toolBoxEngine->registerWidget(widget);
|
||||
+ if (auto toolBox = qobject_cast<QToolBox *>(widget->parent())) {
|
||||
+ _toolBoxEngine->registerWidget(toolBox);
|
||||
}
|
||||
|
||||
- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ _widgetStateEngine->registerWidget(button, AnimationHover | AnimationFocus);
|
||||
|
||||
}
|
||||
|
||||
// groupboxes
|
||||
else if (QGroupBox *groupBox = qobject_cast<QGroupBox *>(widget)) {
|
||||
if (groupBox->isCheckable()) {
|
||||
- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ _widgetStateEngine->registerWidget(groupBox, AnimationHover | AnimationFocus);
|
||||
}
|
||||
}
|
||||
|
||||
// sliders
|
||||
- else if (qobject_cast<QScrollBar *>(widget)) {
|
||||
- _scrollBarEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
- } else if (qobject_cast<QSlider *>(widget)) {
|
||||
- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
- } else if (qobject_cast<QDial *>(widget)) {
|
||||
- _dialEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ else if (auto scrollBar = qobject_cast<QScrollBar *>(widget)) {
|
||||
+ _scrollBarEngine->registerWidget(scrollBar, AnimationHover | AnimationFocus);
|
||||
+ } else if (auto slider = qobject_cast<QSlider *>(widget)) {
|
||||
+ _widgetStateEngine->registerWidget(slider, AnimationHover | AnimationFocus);
|
||||
+ } else if (auto dial = qobject_cast<QDial *>(widget)) {
|
||||
+ _dialEngine->registerWidget(dial, AnimationHover | AnimationFocus);
|
||||
}
|
||||
|
||||
// progress bar
|
||||
@@ -162,24 +162,24 @@ void Animations::registerWidget(QWidget *widget) const
|
||||
|
||||
// header views
|
||||
// need to come before abstract item view, otherwise is skipped
|
||||
- else if (qobject_cast<QHeaderView *>(widget)) {
|
||||
- _headerViewEngine->registerWidget(widget);
|
||||
+ else if (auto headerView = qobject_cast<QHeaderView *>(widget)) {
|
||||
+ _headerViewEngine->registerWidget(headerView);
|
||||
}
|
||||
|
||||
// lists
|
||||
- else if (qobject_cast<QAbstractItemView *>(widget)) {
|
||||
- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ else if (auto itemView = qobject_cast<QAbstractItemView *>(widget)) {
|
||||
+ _inputWidgetEngine->registerWidget(itemView, AnimationHover | AnimationFocus);
|
||||
}
|
||||
|
||||
// tabbar
|
||||
- else if (qobject_cast<QTabBar *>(widget)) {
|
||||
- _tabBarEngine->registerWidget(widget);
|
||||
+ else if (auto tabBar = qobject_cast<QTabBar *>(widget)) {
|
||||
+ _tabBarEngine->registerWidget(tabBar);
|
||||
}
|
||||
|
||||
// scrollarea
|
||||
else if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget)) {
|
||||
- if (scrollArea->frameShadow() == QFrame::Sunken && (widget->focusPolicy() & Qt::StrongFocus)) {
|
||||
- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus);
|
||||
+ if (scrollArea->frameShadow() == QFrame::Sunken && (scrollArea->focusPolicy() & Qt::StrongFocus)) {
|
||||
+ _inputWidgetEngine->registerWidget(scrollArea, AnimationHover | AnimationFocus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ void Animations::registerWidget(QWidget *widget) const
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
-void Animations::unregisterWidget(QWidget *widget) const
|
||||
+void Animations::unregisterWidget(QObject *widget) const
|
||||
{
|
||||
if (!widget) {
|
||||
return;
|
||||
diff --git a/kstyle/animations/breezeanimations.h b/kstyle/animations/breezeanimations.h
|
||||
index 6551900a5..3215e8fb9 100644
|
||||
--- a/kstyle/animations/breezeanimations.h
|
||||
+++ b/kstyle/animations/breezeanimations.h
|
||||
@@ -31,10 +31,10 @@ public:
|
||||
explicit Animations();
|
||||
|
||||
//* register animations corresponding to given widget, depending on its type.
|
||||
- void registerWidget(QWidget *widget) const;
|
||||
+ void registerWidget(QObject *widget) const;
|
||||
|
||||
/** unregister all animations associated to a widget */
|
||||
- void unregisterWidget(QWidget *widget) const;
|
||||
+ void unregisterWidget(QObject *widget) const;
|
||||
|
||||
//* enability engine
|
||||
[[nodiscard]] WidgetStateEngine &widgetEnabilityEngine() const
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 75201d1e63d82f7282c8bedcc7cc3d2417b1e123 Mon Sep 17 00:00:00 2001
|
||||
From: Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
Date: Sat, 24 May 2025 09:40:01 +0200
|
||||
Subject: [PATCH 2/3] kstyle: Use styleObject for widgetStateEngine in
|
||||
CheckBox/RadioButton
|
||||
|
||||
Prepares it for doing the animation also with Qt Quick Controls
|
||||
without an actual QWidget.
|
||||
---
|
||||
kstyle/breezestyle.cpp | 44 ++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 29 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp
|
||||
index 09cee6003..19149c382 100644
|
||||
--- a/kstyle/breezestyle.cpp
|
||||
+++ b/kstyle/breezestyle.cpp
|
||||
@@ -4738,6 +4738,8 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter
|
||||
//___________________________________________________________________________________
|
||||
bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
+ const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+
|
||||
// copy rect and palette
|
||||
const auto &rect(option->rect);
|
||||
const auto &palette(option->palette);
|
||||
@@ -4757,15 +4759,15 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter
|
||||
}
|
||||
|
||||
// animation state
|
||||
- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver);
|
||||
- _animations->widgetStateEngine().updateState(widget, AnimationPressed, checkBoxState != CheckOff);
|
||||
+ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver);
|
||||
+ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, checkBoxState != CheckOff);
|
||||
auto target = checkBoxState;
|
||||
- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) {
|
||||
+ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) {
|
||||
checkBoxState = CheckAnimated;
|
||||
}
|
||||
- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed));
|
||||
+ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed));
|
||||
|
||||
- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover));
|
||||
+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover));
|
||||
|
||||
// render
|
||||
_helper->renderCheckBoxBackground(painter, rect, palette, checkBoxState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation);
|
||||
@@ -4777,6 +4779,8 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter
|
||||
//___________________________________________________________________________________
|
||||
bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
+ const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+
|
||||
// copy rect and palette
|
||||
const auto &rect(option->rect);
|
||||
const auto &palette(option->palette);
|
||||
@@ -4791,19 +4795,27 @@ bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPaint
|
||||
RadioButtonState radioButtonState((state & State_On) ? RadioOn : RadioOff);
|
||||
|
||||
// animation state
|
||||
- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver);
|
||||
- _animations->widgetStateEngine().updateState(widget, AnimationPressed, radioButtonState != RadioOff);
|
||||
- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) {
|
||||
+ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver);
|
||||
+ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, radioButtonState != RadioOff);
|
||||
+ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) {
|
||||
radioButtonState = RadioAnimated;
|
||||
}
|
||||
- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed));
|
||||
+ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed));
|
||||
|
||||
// colors
|
||||
- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover));
|
||||
+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover));
|
||||
|
||||
// render
|
||||
- _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation);
|
||||
- _helper->renderRadioButton(painter, rect, palette, mouseOver, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation, opacity);
|
||||
+ _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(styleObject, option, mouseOver), sunken, animation);
|
||||
+ _helper->renderRadioButton(painter,
|
||||
+ rect,
|
||||
+ palette,
|
||||
+ mouseOver,
|
||||
+ radioButtonState,
|
||||
+ hasHighlightNeutral(styleObject, option, mouseOver),
|
||||
+ sunken,
|
||||
+ animation,
|
||||
+ opacity);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5450,6 +5462,8 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint
|
||||
return true;
|
||||
}
|
||||
|
||||
+ const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+
|
||||
// copy palette and rect
|
||||
const auto &palette(option->palette);
|
||||
const auto &rect(option->rect);
|
||||
@@ -5501,10 +5515,10 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint
|
||||
const bool hasFocus(enabled && (state & State_HasFocus));
|
||||
|
||||
// update animation state
|
||||
- _animations->widgetStateEngine().updateState(widget, AnimationFocus, hasFocus);
|
||||
+ _animations->widgetStateEngine().updateState(styleObject, AnimationFocus, hasFocus);
|
||||
|
||||
- const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(widget, AnimationFocus));
|
||||
- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationFocus));
|
||||
+ const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(styleObject, AnimationFocus));
|
||||
+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationFocus));
|
||||
// focus color
|
||||
QColor focusColor;
|
||||
if (isFocusAnimated) {
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From a572df8f099969919544dbc2478de6aa2082a705 Mon Sep 17 00:00:00 2001
|
||||
From: Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
Date: Sat, 24 May 2025 09:54:44 +0200
|
||||
Subject: [PATCH 3/3] kstyle: Register Qt Quick Controls with animations
|
||||
|
||||
Since it's all software-rendered and indirect, only the
|
||||
CheckBox and RadioButton controls are actually wired up
|
||||
since the rest of the animations is quite subtle.
|
||||
---
|
||||
kstyle/animations/breezeanimations.cpp | 9 +++++++++
|
||||
kstyle/breezestyle.cpp | 4 ++++
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp
|
||||
index ceab53802..5285f5daf 100644
|
||||
--- a/kstyle/animations/breezeanimations.cpp
|
||||
+++ b/kstyle/animations/breezeanimations.cpp
|
||||
@@ -100,6 +100,15 @@ void Animations::registerWidget(QObject *widget) const
|
||||
// install animation timers
|
||||
// for optimization, one should put with most used widgets here first
|
||||
|
||||
+ // KQuickStyleItem.
|
||||
+ const QString elementType = widget->property("elementType").toString();
|
||||
+ if (!elementType.isEmpty()) {
|
||||
+ if (elementType == QLatin1String("checkbox") || elementType == QLatin1String("radiobutton")) {
|
||||
+ _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// buttons
|
||||
if (auto toolButton = qobject_cast<QToolButton *>(widget)) {
|
||||
_toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus);
|
||||
diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp
|
||||
index 19149c382..e549803f1 100644
|
||||
--- a/kstyle/breezestyle.cpp
|
||||
+++ b/kstyle/breezestyle.cpp
|
||||
@@ -4739,6 +4739,7 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter
|
||||
bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+ isQtQuickControl(option, widget); // registers it with widgetStateEngine.
|
||||
|
||||
// copy rect and palette
|
||||
const auto &rect(option->rect);
|
||||
@@ -4780,6 +4781,7 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter
|
||||
bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+ isQtQuickControl(option, widget); // registers it with widgetStateEngine.
|
||||
|
||||
// copy rect and palette
|
||||
const auto &rect(option->rect);
|
||||
@@ -5463,6 +5465,7 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint
|
||||
}
|
||||
|
||||
const QObject *styleObject = widget ? widget : option->styleObject;
|
||||
+ isQtQuickControl(option, widget); // registers it with widgetStateEngine.
|
||||
|
||||
// copy palette and rect
|
||||
const auto &palette(option->palette);
|
||||
@@ -8460,6 +8463,7 @@ bool Style::isQtQuickControl(const QStyleOption *option, const QWidget *widget)
|
||||
if (!widget && option) {
|
||||
if (const auto item = qobject_cast<QQuickItem *>(option->styleObject)) {
|
||||
_windowManager->registerQuickItem(item);
|
||||
+ _animations->registerWidget(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
||||
3
roles/kde/patches/dolphin/patches.txt
Normal file
3
roles/kde/patches/dolphin/patches.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Gear 25.08.0:
|
||||
|
||||
Pr 946 https://invent.kde.org/system/dolphin/-/merge_requests/946
|
||||
3978
roles/kde/patches/dolphin/pr946.patch
Normal file
3978
roles/kde/patches/dolphin/pr946.patch
Normal file
File diff suppressed because it is too large
Load diff
7
roles/kde/patches/kwin/patches.txt
Normal file
7
roles/kde/patches/kwin/patches.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Plasma 6.5.0:
|
||||
Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612
|
||||
Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823
|
||||
|
||||
Plasma 6.4.2:
|
||||
Pr 7822 https://invent.kde.org/plasma/kwin/-/merge_requests/7822
|
||||
Pr 7829 https://invent.kde.org/plasma/kwin/-/merge_requests/7829
|
||||
2101
roles/kde/patches/kwin/pr3612.patch
Normal file
2101
roles/kde/patches/kwin/pr3612.patch
Normal file
File diff suppressed because it is too large
Load diff
40
roles/kde/patches/kwin/pr7822.patch
Normal file
40
roles/kde/patches/kwin/pr7822.patch
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
From 3ac297b99540eae81568edca1e550ca7d1d6c01f Mon Sep 17 00:00:00 2001
|
||||
From: Ismael Asensio <isma.af@gmail.com>
|
||||
Date: Tue, 24 Jun 2025 17:08:00 +0200
|
||||
Subject: [PATCH] plugins/fadingpopups: Blacklist spectacle popup menus from
|
||||
fading effect
|
||||
|
||||
Spectacle can trigger a screenshot from a popup menu. This menu needs
|
||||
to get hidden immediately with no effects, to avoid appearing on the
|
||||
screenshot.
|
||||
|
||||
BUG: 505803
|
||||
FIXED-IN: 6.4.2
|
||||
|
||||
|
||||
(cherry picked from commit 99f6418e3c2e044eb1f4e8bedcdccac55f1a01d4)
|
||||
|
||||
Co-authored-by: Ismael Asensio <isma.af@gmail.com>
|
||||
---
|
||||
src/plugins/fadingpopups/package/contents/code/main.js | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/fadingpopups/package/contents/code/main.js b/src/plugins/fadingpopups/package/contents/code/main.js
|
||||
index f0764b42ac6..7c00640ae8f 100644
|
||||
--- a/src/plugins/fadingpopups/package/contents/code/main.js
|
||||
+++ b/src/plugins/fadingpopups/package/contents/code/main.js
|
||||
@@ -17,7 +17,10 @@ var blacklist = [
|
||||
// The lockscreen isn't a popup window
|
||||
"kscreenlocker_greet kscreenlocker_greet",
|
||||
// KDE Plasma splash screen has to be animated only by the login effect.
|
||||
- "ksplashqml ksplashqml"
|
||||
+ "ksplashqml ksplashqml",
|
||||
+ // Spectacle can trigger a screenshot from a popup menu
|
||||
+ "spectacle org.kde.spectacle",
|
||||
+ "spectacle spectacle",
|
||||
];
|
||||
|
||||
function isPopupWindow(window) {
|
||||
--
|
||||
GitLab
|
||||
|
||||
26
roles/kde/patches/kwin/pr7823.patch
Normal file
26
roles/kde/patches/kwin/pr7823.patch
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
From a1868942fbc2ad5de4c053dd17335dff34d81779 Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Wed, 25 Jun 2025 14:10:18 +0300
|
||||
Subject: [PATCH] plugins/login: Reduce animation duration
|
||||
|
||||
This makes the startup feel a bit faster.
|
||||
---
|
||||
src/plugins/login/package/contents/code/main.js | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/login/package/contents/code/main.js b/src/plugins/login/package/contents/code/main.js
|
||||
index 7f849a6e2e6..e3ad0b76c07 100644
|
||||
--- a/src/plugins/login/package/contents/code/main.js
|
||||
+++ b/src/plugins/login/package/contents/code/main.js
|
||||
@@ -11,7 +11,7 @@
|
||||
"use strict";
|
||||
|
||||
var loginEffect = {
|
||||
- duration: animationTime(1000),
|
||||
+ duration: animationTime(500),
|
||||
isFadeToBlack: false,
|
||||
loadConfig: function () {
|
||||
loginEffect.isFadeToBlack = effect.readConfig("FadeToBlack", false);
|
||||
--
|
||||
GitLab
|
||||
|
||||
85
roles/kde/patches/kwin/pr7829.patch
Normal file
85
roles/kde/patches/kwin/pr7829.patch
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
From 4ddb4a23d5f453cf890c9f1b1aa5429150991db3 Mon Sep 17 00:00:00 2001
|
||||
From: David Redondo <kde@david-redondo.de>
|
||||
Date: Thu, 26 Jun 2025 17:00:07 +0200
|
||||
Subject: [PATCH] scene: Skip visibility check for the Item itself in
|
||||
framePainted
|
||||
|
||||
Fixes offscreen rendering and window thumbnails for hidden windows
|
||||
not udpating.
|
||||
Co-authored-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
---
|
||||
src/scene/item.cpp | 9 +++++----
|
||||
src/scene/item.h | 2 +-
|
||||
src/scene/rootitem.cpp | 9 ---------
|
||||
src/scene/rootitem.h | 2 --
|
||||
4 files changed, 6 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/scene/item.cpp b/src/scene/item.cpp
|
||||
index 2637a131dbd..eb2b6b46977 100644
|
||||
--- a/src/scene/item.cpp
|
||||
+++ b/src/scene/item.cpp
|
||||
@@ -648,12 +648,13 @@ void Item::removeEffect()
|
||||
|
||||
void Item::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp)
|
||||
{
|
||||
- if (!isVisible() || workspace()->outputAt(mapToScene(boundingRect()).center()) != output) {
|
||||
- return;
|
||||
- }
|
||||
+ // The visibility of the item itself is not checked here to be able to paint hidden items for
|
||||
+ // things like screncasts or thumbnails
|
||||
handleFramePainted(output, frame, timestamp);
|
||||
for (const auto child : std::as_const(m_childItems)) {
|
||||
- child->framePainted(output, frame, timestamp);
|
||||
+ if (child->explicitVisible() && workspace()->outputAt(child->mapToScene(child->boundingRect()).center()) == output) {
|
||||
+ child->framePainted(output, frame, timestamp);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/scene/item.h b/src/scene/item.h
|
||||
index acb29994328..d42b32abf7b 100644
|
||||
--- a/src/scene/item.h
|
||||
+++ b/src/scene/item.h
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
void addEffect();
|
||||
void removeEffect();
|
||||
|
||||
- virtual void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp);
|
||||
+ void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp);
|
||||
|
||||
bool isAncestorOf(const Item *item) const;
|
||||
|
||||
diff --git a/src/scene/rootitem.cpp b/src/scene/rootitem.cpp
|
||||
index fe0cecc76e3..466a25ce828 100644
|
||||
--- a/src/scene/rootitem.cpp
|
||||
+++ b/src/scene/rootitem.cpp
|
||||
@@ -14,13 +14,4 @@ RootItem::RootItem(Scene *scene)
|
||||
setScene(scene);
|
||||
}
|
||||
|
||||
-void RootItem::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp)
|
||||
-{
|
||||
- handleFramePainted(output, frame, timestamp);
|
||||
- const auto children = childItems();
|
||||
- for (const auto child : children) {
|
||||
- child->framePainted(output, frame, timestamp);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
} // namespace KWin
|
||||
diff --git a/src/scene/rootitem.h b/src/scene/rootitem.h
|
||||
index 45fa1359c84..43b3cdb90e9 100644
|
||||
--- a/src/scene/rootitem.h
|
||||
+++ b/src/scene/rootitem.h
|
||||
@@ -20,8 +20,6 @@ class KWIN_EXPORT RootItem : public Item
|
||||
|
||||
public:
|
||||
explicit RootItem(Scene *scene);
|
||||
-
|
||||
- void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) override;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
--
|
||||
GitLab
|
||||
|
||||
4
roles/kde/patches/plasma-nm/patches.txt
Normal file
4
roles/kde/patches/plasma-nm/patches.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Plasma 6.5.0:
|
||||
|
||||
Pr 439 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/439
|
||||
Pr 442 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/442
|
||||
140
roles/kde/patches/plasma-nm/pr439.patch
Normal file
140
roles/kde/patches/plasma-nm/pr439.patch
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
From ac32824009397188131aab4fcc3394fcc4551c5c Mon Sep 17 00:00:00 2001
|
||||
From: Nate Graham <nate@kde.org>
|
||||
Date: Tue, 10 Jun 2025 15:43:13 -0600
|
||||
Subject: [PATCH 1/2] applet: handle some more states
|
||||
|
||||
1. Looking for Wi-Fi networks but haven't found any yet
|
||||
2. NetworkManager isn't running
|
||||
|
||||
FEATURE: 485982
|
||||
BUG: 462454
|
||||
FIXED-IN: 6.5.0
|
||||
---
|
||||
applet/contents/ui/ConnectionListPage.qml | 15 ++++++++++++---
|
||||
applet/contents/ui/Toolbar.qml | 3 ++-
|
||||
applet/metadata.json | 1 -
|
||||
libs/networkstatus.h | 3 +--
|
||||
4 files changed, 15 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml
|
||||
index b9a949d87..056f52de3 100644
|
||||
--- a/applet/contents/ui/ConnectionListPage.qml
|
||||
+++ b/applet/contents/ui/ConnectionListPage.qml
|
||||
@@ -101,9 +101,12 @@ ColumnLayout {
|
||||
if (toolbar.displayplaneModeMessage) {
|
||||
return "network-flightmode-on"
|
||||
}
|
||||
- if (toolbar.displayWifiMessage) {
|
||||
+ if (toolbar.displayWifiOffMessage) {
|
||||
return "network-wireless-off"
|
||||
}
|
||||
+ if (toolbar.displayWifiConnectingMessage) {
|
||||
+ return "view-refresh-symbolic"
|
||||
+ }
|
||||
if (toolbar.displayWwanMessage) {
|
||||
return "network-mobile-off"
|
||||
}
|
||||
@@ -113,19 +116,25 @@ ColumnLayout {
|
||||
if (toolbar.displayplaneModeMessage) {
|
||||
return i18n("Airplane mode is enabled")
|
||||
}
|
||||
- if (toolbar.displayWifiMessage) {
|
||||
+ if (toolbar.displayWifiOffMessage) {
|
||||
if (toolbar.displayWwanMessage) {
|
||||
return i18n("Wireless and mobile networks are deactivated")
|
||||
}
|
||||
return i18n("Wireless is deactivated")
|
||||
}
|
||||
+ if (toolbar.displayWifiConnectingMessage) {
|
||||
+ return i18n("Looking for wireless networks")
|
||||
+ }
|
||||
if (toolbar.displayWwanMessage) {
|
||||
return i18n("Mobile network is deactivated")
|
||||
}
|
||||
if (toolbar.searchTextField.text.length > 0) {
|
||||
return i18n("No matches")
|
||||
}
|
||||
- return i18n("No available connections")
|
||||
+ if (connectionListPage.nmStatus.connectivity === NMQt.NetworkManager.Full) {
|
||||
+ return i18n("No available connections")
|
||||
+ }
|
||||
+ return nmStatus.checkUnknownReason()
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/applet/contents/ui/Toolbar.qml b/applet/contents/ui/Toolbar.qml
|
||||
index 87b3f1654..0d382109b 100644
|
||||
--- a/applet/contents/ui/Toolbar.qml
|
||||
+++ b/applet/contents/ui/Toolbar.qml
|
||||
@@ -16,7 +16,8 @@ import org.kde.kcmutils as KCMUtils
|
||||
RowLayout {
|
||||
id: toolbar
|
||||
|
||||
- readonly property var displayWifiMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible
|
||||
+ readonly property var displayWifiOffMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible
|
||||
+ readonly property var displayWifiConnectingMessage: wifiSwitchButton.checked && wifiSwitchButton.visible
|
||||
readonly property var displayWwanMessage: !wwanSwitchButton.checked && wwanSwitchButton.visible
|
||||
readonly property var displayplaneModeMessage: planeModeSwitchButton.checked && planeModeSwitchButton.visible
|
||||
|
||||
diff --git a/applet/metadata.json b/applet/metadata.json
|
||||
index 0ca36a2b7..2f12891b5 100644
|
||||
--- a/applet/metadata.json
|
||||
+++ b/applet/metadata.json
|
||||
@@ -210,6 +210,5 @@
|
||||
"X-KDE-Keywords[zh_CN]": "network,internet,ethernet,wireless,wifi,wlan,vpn,wangluo,hulianwang,yitaiwang,juyuwang,wuxianwangluo,xunizhuanyongwangluo,网络,互联网,以太网,局域网,无线网络,虚拟专用网络",
|
||||
"X-KDE-Keywords[zh_TW]": "網路,網絡,網際網路,乙太網路,以太網路,無線",
|
||||
"X-Plasma-API-Minimum-Version": "6.0",
|
||||
- "X-Plasma-DBusActivationService": "org.freedesktop.NetworkManager",
|
||||
"X-Plasma-NotificationAreaCategory": "Hardware"
|
||||
}
|
||||
diff --git a/libs/networkstatus.h b/libs/networkstatus.h
|
||||
index aa88bf7c5..a885f04dd 100644
|
||||
--- a/libs/networkstatus.h
|
||||
+++ b/libs/networkstatus.h
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
QString activeConnections() const;
|
||||
QString networkStatus() const;
|
||||
NetworkManager::Connectivity connectivity() const;
|
||||
+ Q_INVOKABLE QString checkUnknownReason() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void activeConnectionsChanged();
|
||||
@@ -75,8 +76,6 @@ private:
|
||||
QString m_activeConnections;
|
||||
QString m_networkStatus;
|
||||
NetworkManager::Connectivity m_connectivity = NetworkManager::UnknownConnectivity;
|
||||
-
|
||||
- QString checkUnknownReason() const;
|
||||
};
|
||||
|
||||
#endif // PLAMA_NM_NETWORK_STATUS_H
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From a45534cd9c19f267075fe4261087045f1f3a9318 Mon Sep 17 00:00:00 2001
|
||||
From: Nate Graham <nate@kde.org>
|
||||
Date: Wed, 11 Jun 2025 10:14:40 -0600
|
||||
Subject: [PATCH 2/2] Rephrase "NetworkManager not running" message to be more
|
||||
user-friendly
|
||||
|
||||
---
|
||||
libs/networkstatus.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libs/networkstatus.cpp b/libs/networkstatus.cpp
|
||||
index c89ca9fca..b778eedda 100644
|
||||
--- a/libs/networkstatus.cpp
|
||||
+++ b/libs/networkstatus.cpp
|
||||
@@ -253,7 +253,7 @@ QString NetworkStatus::checkUnknownReason() const
|
||||
{
|
||||
// Check if NetworkManager is running.
|
||||
if (!QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral(NM_DBUS_INTERFACE))) {
|
||||
- return i18n("NetworkManager not running");
|
||||
+ return i18nc("@info:status", "NetworkManager service is not running");
|
||||
}
|
||||
|
||||
// Check for compatible NetworkManager version.
|
||||
--
|
||||
GitLab
|
||||
|
||||
168
roles/kde/patches/plasma-nm/pr442.patch
Normal file
168
roles/kde/patches/plasma-nm/pr442.patch
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
From 63a9d544dc4f5160f28e5f3203a2c0a5e639e5ac Mon Sep 17 00:00:00 2001
|
||||
From: Nate Graham <nate@kde.org>
|
||||
Date: Fri, 13 Jun 2025 12:24:22 -0600
|
||||
Subject: [PATCH] applet: use standard section headers
|
||||
|
||||
We have them, so we might as well use them. This lets us get rid of a
|
||||
bunch of complex and fragile code that's responsible for the existing
|
||||
separator.
|
||||
---
|
||||
applet/contents/ui/ConnectionItem.qml | 14 -----
|
||||
applet/contents/ui/ConnectionListPage.qml | 10 ++--
|
||||
applet/contents/ui/ListItem.qml | 64 -----------------------
|
||||
libs/models/networkmodelitem.cpp | 8 ++-
|
||||
4 files changed, 12 insertions(+), 84 deletions(-)
|
||||
delete mode 100644 applet/contents/ui/ListItem.qml
|
||||
|
||||
diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml
|
||||
index ed154e633..5bb5c530c 100644
|
||||
--- a/applet/contents/ui/ConnectionItem.qml
|
||||
+++ b/applet/contents/ui/ConnectionItem.qml
|
||||
@@ -321,20 +321,6 @@ PlasmaExtras.ExpandableListItem {
|
||||
}
|
||||
}
|
||||
|
||||
- onDeactivatedChanged: {
|
||||
- /* Separator is part of section, which is visible only when available connections exist. Need to determine
|
||||
- if there is a connection in use, to show Separator. Otherwise need to hide it from the top of the list.
|
||||
- Connections in use are always on top, only need to check the first one. */
|
||||
- if (appletProxyModel.data(appletProxyModel.index(0, 0), PlasmaNM.NetworkModel.SectionRole) !== "Available connections") {
|
||||
- if (connectionView.showSeparator != true) {
|
||||
- connectionView.showSeparator = true
|
||||
- }
|
||||
- return
|
||||
- }
|
||||
- connectionView.showSeparator = false
|
||||
- return
|
||||
- }
|
||||
-
|
||||
onItemCollapsed: {
|
||||
connectionItem.customExpandedViewContent = detailsComponent;
|
||||
setDelayModelUpdates(false);
|
||||
diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml
|
||||
index b62da252c..d8ebd2c54 100644
|
||||
--- a/applet/contents/ui/ConnectionListPage.qml
|
||||
+++ b/applet/contents/ui/ConnectionListPage.qml
|
||||
@@ -8,7 +8,7 @@ import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.2
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
-import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
+import org.kde.plasma.extras as PlasmaExtras
|
||||
import org.kde.plasma.networkmanagement as PlasmaNM
|
||||
import org.kde.networkmanager as NMQt
|
||||
|
||||
@@ -55,7 +55,6 @@ ColumnLayout {
|
||||
id: connectionView
|
||||
|
||||
property int currentVisibleButtonIndex: -1
|
||||
- property bool showSeparator: false
|
||||
|
||||
Keys.onDownPressed: event => {
|
||||
connectionView.incrementCurrentIndex();
|
||||
@@ -80,9 +79,10 @@ ColumnLayout {
|
||||
model: appletProxyModel
|
||||
currentIndex: -1
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
- section.property: showSeparator ? "Section" : ""
|
||||
- section.delegate: ListItem {
|
||||
- separator: true
|
||||
+ section.property: "Section"
|
||||
+ section.delegate: PlasmaExtras.ListSectionHeader {
|
||||
+ width: connectionView.width - connectionView.leftMargin - connectionView.rightMargin
|
||||
+ text: section
|
||||
}
|
||||
highlight: PlasmaExtras.Highlight { }
|
||||
highlightMoveDuration: Kirigami.Units.shortDuration
|
||||
diff --git a/applet/contents/ui/ListItem.qml b/applet/contents/ui/ListItem.qml
|
||||
deleted file mode 100644
|
||||
index bfe1390d1..000000000
|
||||
--- a/applet/contents/ui/ListItem.qml
|
||||
+++ /dev/null
|
||||
@@ -1,64 +0,0 @@
|
||||
-/*
|
||||
- SPDX-FileCopyrightText: 2010 Marco Martin <notmart@gmail.com>
|
||||
- SPDX-FileCopyrightText: 2016 Jan Grulich <jgrulich@redhat.com>
|
||||
- SPDX-FileCopyrightText: 2020 George Vogiatzis <gvgeo@protonmail.com>
|
||||
-
|
||||
- SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
-*/
|
||||
-
|
||||
-import QtQuick 2.1
|
||||
-import org.kde.kirigami 2.20 as Kirigami
|
||||
-import org.kde.ksvg 1.0 as KSvg
|
||||
-
|
||||
-/**
|
||||
- * Ignores the theme's listItem margins, and uses custom highlight(pressed) area.
|
||||
- * Could break some themes but the majority look fine.
|
||||
- * Also includes a separator to be used in sections.
|
||||
- */
|
||||
-MouseArea {
|
||||
- id: listItem
|
||||
-
|
||||
- property bool checked: false
|
||||
- property bool separator: false
|
||||
- property rect highlightRect: Qt.rect(0, 0, width, height)
|
||||
-
|
||||
- width: parent.width
|
||||
-
|
||||
- // Sections have spacing above but not below. Will use 2 of them below.
|
||||
- height: separator ? separatorLine.height + Kirigami.Units.smallSpacing * 3 : parent.height
|
||||
- hoverEnabled: true
|
||||
-
|
||||
- KSvg.SvgItem {
|
||||
- id: separatorLine
|
||||
- anchors {
|
||||
- horizontalCenter: parent.horizontalCenter
|
||||
- top: parent.top
|
||||
- topMargin: Kirigami.Units.smallSpacing
|
||||
- }
|
||||
- imagePath: "widgets/line"
|
||||
- elementId: "horizontal-line"
|
||||
- width: parent.width - Kirigami.Units.gridUnit * 2
|
||||
- visible: listItem.separator
|
||||
- }
|
||||
-
|
||||
- KSvg.FrameSvgItem {
|
||||
- id: background
|
||||
- imagePath: "widgets/listitem"
|
||||
- prefix: "normal"
|
||||
- anchors.fill: parent
|
||||
- visible: listItem.separator ? false : true
|
||||
- }
|
||||
-
|
||||
- KSvg.FrameSvgItem {
|
||||
- id: pressed
|
||||
- imagePath: "widgets/listitem"
|
||||
- prefix: "pressed"
|
||||
- opacity: listItem.checked ? 1 : 0
|
||||
- Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
|
||||
-
|
||||
- x: listItem.highlightRect.x
|
||||
- y: listItem.highlightRect.y
|
||||
- height: listItem.highlightRect.height
|
||||
- width: listItem.highlightRect.width
|
||||
- }
|
||||
-}
|
||||
diff --git a/libs/models/networkmodelitem.cpp b/libs/models/networkmodelitem.cpp
|
||||
index b92ec0df2..4d7cbd77d 100644
|
||||
--- a/libs/models/networkmodelitem.cpp
|
||||
+++ b/libs/models/networkmodelitem.cpp
|
||||
@@ -344,7 +344,13 @@ QString NetworkModelItem::originalName() const
|
||||
QString NetworkModelItem::sectionType() const
|
||||
{
|
||||
if (m_connectionState == NetworkManager::ActiveConnection::Deactivated) {
|
||||
- return QStringLiteral("Available connections");
|
||||
+ return i18nc("@title:column header for list of available network connections", "Available");
|
||||
+ // clang-format off
|
||||
+ } else if (m_connectionState == NetworkManager::ActiveConnection::Activating
|
||||
+ || m_connectionState == NetworkManager::ActiveConnection::Activated
|
||||
+ || m_connectionState == NetworkManager::ActiveConnection::Deactivating) {
|
||||
+ // clang-format on
|
||||
+ return i18nc("@title:column header for list of connected network connections", "Connected");
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
||||
6
roles/kde/patches/plasma-workspace/patches.txt
Normal file
6
roles/kde/patches/plasma-workspace/patches.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Plasma 6.5.0:
|
||||
|
||||
Pr 5589 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5589
|
||||
Pr 5626 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5626
|
||||
Pr 5627 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5627
|
||||
Pr 5628 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628
|
||||
37
roles/kde/patches/plasma-workspace/pr5589.patch
Normal file
37
roles/kde/patches/plasma-workspace/pr5589.patch
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
From 2278398309c68ce401a8e35b193fca3782391a4a Mon Sep 17 00:00:00 2001
|
||||
From: Nate Graham <nate@kde.org>
|
||||
Date: Thu, 12 Jun 2025 09:15:15 -0600
|
||||
Subject: [PATCH] applets/devicenotifier: use standard section header
|
||||
|
||||
No need for a custom header here when we have a standard one.
|
||||
|
||||
CCBUG: 442724
|
||||
---
|
||||
.../package/contents/ui/FullRepresentation.qml | 10 ++--------
|
||||
1 file changed, 2 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml
|
||||
index 967223e0a1a..a0c28df45fe 100644
|
||||
--- a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml
|
||||
+++ b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml
|
||||
@@ -132,15 +132,9 @@ PlasmaExtras.Representation {
|
||||
|
||||
section {
|
||||
property: "deviceType"
|
||||
- delegate: Item {
|
||||
- height: Math.floor(childrenRect.height)
|
||||
+ delegate: PlasmaExtras.ListSectionHeader {
|
||||
width: notifierDialog.width - (scrollView.PlasmaComponents3.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 2 : 0)
|
||||
- Kirigami.Heading {
|
||||
- level: 3
|
||||
- opacity: 0.6
|
||||
- text: section
|
||||
- textFormat: Text.PlainText
|
||||
- }
|
||||
+ text: section
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
GitLab
|
||||
|
||||
102
roles/kde/patches/plasma-workspace/pr5626.patch
Normal file
102
roles/kde/patches/plasma-workspace/pr5626.patch
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
From 9fabf42c39a25308739dd3483881cc889243bf58 Mon Sep 17 00:00:00 2001
|
||||
From: Kristen McWilliam <kristen@kde.org>
|
||||
Date: Tue, 24 Jun 2025 17:44:33 -0400
|
||||
Subject: [PATCH] applets/notifications: Add actions to missed notifications
|
||||
notification
|
||||
|
||||
When a notification is displayed informing the user that notifications were missed while in Do Not
|
||||
Disturb, now clicking the button or the notification itself will open the notifications applet to
|
||||
show the missed notifications.
|
||||
|
||||
BUG: 502423
|
||||
---
|
||||
.../package/contents/ui/main.qml | 10 ++++++
|
||||
libnotificationmanager/notifications.cpp | 34 ++++++++++++++-----
|
||||
libnotificationmanager/notifications.h | 7 ++++
|
||||
3 files changed, 42 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/applets/notifications/package/contents/ui/main.qml b/applets/notifications/package/contents/ui/main.qml
|
||||
index c96afa0558d..ab66a52f45e 100644
|
||||
--- a/applets/notifications/package/contents/ui/main.qml
|
||||
+++ b/applets/notifications/package/contents/ui/main.qml
|
||||
@@ -268,4 +268,14 @@ PlasmoidItem {
|
||||
Component.onDestruction: {
|
||||
Globals.forget(root);
|
||||
}
|
||||
+
|
||||
+ Connections {
|
||||
+ target: Globals.popupNotificationsModel
|
||||
+
|
||||
+ // The user requested to show the notifications popup, probably by
|
||||
+ // clicking the "Missed Notifications in Do Not Disturb" notification.
|
||||
+ function onShowNotificationsRequested(): void {
|
||||
+ root.expanded = true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp
|
||||
index 2cba1360b10..7b5cd9d68c4 100644
|
||||
--- a/libnotificationmanager/notifications.cpp
|
||||
+++ b/libnotificationmanager/notifications.cpp
|
||||
@@ -903,15 +903,31 @@ void Notifications::showInhibitionSummary(Urgency urgency, const QStringList &bl
|
||||
return;
|
||||
}
|
||||
|
||||
- KNotification::event(u"inhibitionSummary"_s,
|
||||
- i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited),
|
||||
- i18ncp("@info",
|
||||
- "%1 notification was received while Do Not Disturb was active.",
|
||||
- "%1 notifications were received while Do Not Disturb was active.",
|
||||
- inhibited),
|
||||
- u"preferences-desktop-notification-bell"_s,
|
||||
- KNotification::CloseOnTimeout,
|
||||
- u"libnotificationmanager"_s);
|
||||
+ KNotification *notification = new KNotification(u"inhibitionSummary"_s);
|
||||
+ notification->setTitle(i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited));
|
||||
+ notification->setText(i18ncp("@info",
|
||||
+ "%1 notification was received while Do Not Disturb was active.",
|
||||
+ "%1 notifications were received while Do Not Disturb was active.",
|
||||
+ inhibited));
|
||||
+ notification->setIconName(u"preferences-desktop-notification-bell"_s);
|
||||
+ notification->setFlags(KNotification::CloseOnTimeout);
|
||||
+ notification->setComponentName(u"libnotificationmanager"_s);
|
||||
+
|
||||
+ const QString showNotificationsText = i18nc( //
|
||||
+ "@action:button Show the notifications popup; translate this in as short a form as possible",
|
||||
+ "Show Notifications");
|
||||
+
|
||||
+ const KNotificationAction *defaultShowNotificationsAction = notification->addDefaultAction(showNotificationsText);
|
||||
+ connect(defaultShowNotificationsAction, &KNotificationAction::activated, this, [this]() {
|
||||
+ Q_EMIT showNotificationsRequested();
|
||||
+ });
|
||||
+
|
||||
+ const KNotificationAction *showNotificationsAction = notification->addAction(showNotificationsText);
|
||||
+ connect(showNotificationsAction, &KNotificationAction::activated, this, [this]() {
|
||||
+ Q_EMIT showNotificationsRequested();
|
||||
+ });
|
||||
+
|
||||
+ notification->sendEvent();
|
||||
}
|
||||
|
||||
QVariant Notifications::data(const QModelIndex &index, int role) const
|
||||
diff --git a/libnotificationmanager/notifications.h b/libnotificationmanager/notifications.h
|
||||
index e927c472c8f..8544b6271ae 100644
|
||||
--- a/libnotificationmanager/notifications.h
|
||||
+++ b/libnotificationmanager/notifications.h
|
||||
@@ -597,6 +597,13 @@ Q_SIGNALS:
|
||||
void jobsPercentageChanged();
|
||||
void windowChanged(QWindow *window);
|
||||
|
||||
+ /**
|
||||
+ * Emitted when the user has requested to show the notifications popup.
|
||||
+ *
|
||||
+ * This is typically connected to a button in the "Missed Notifications in Do Not Disturb" notification.
|
||||
+ */
|
||||
+ void showNotificationsRequested();
|
||||
+
|
||||
protected:
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
--
|
||||
GitLab
|
||||
|
||||
157
roles/kde/patches/plasma-workspace/pr5627.patch
Normal file
157
roles/kde/patches/plasma-workspace/pr5627.patch
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
From 1641ea3897d565d672e29a7524ce4171ddbcfd32 Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Wed, 25 Jun 2025 14:00:05 +0300
|
||||
Subject: [PATCH 1/2] shell: Set desktop ksplash stage when all desktop views
|
||||
are ready
|
||||
|
||||
If there are two outputs and the wallpaper for the first one is ready
|
||||
but for the second one is not, the ksplash will be notified about the
|
||||
desktop stage.
|
||||
|
||||
This changes fixes checkAllDesktopsUiReady() so it sets the desktop
|
||||
stage only if all desktop views are ready.
|
||||
---
|
||||
shell/shellcorona.cpp | 28 +++++++++++++++-------------
|
||||
shell/shellcorona.h | 2 +-
|
||||
2 files changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp
|
||||
index 37d93d05353..65c8ccc272e 100644
|
||||
--- a/shell/shellcorona.cpp
|
||||
+++ b/shell/shellcorona.cpp
|
||||
@@ -1338,6 +1338,8 @@ void ShellCorona::removeDesktop(DesktopView *desktopView)
|
||||
|
||||
desktopView->destroy();
|
||||
desktopView->containment()->reactToScreenChange();
|
||||
+
|
||||
+ checkAllDesktopsUiReady();
|
||||
}
|
||||
|
||||
PanelView *ShellCorona::panelView(Plasma::Containment *containment) const
|
||||
@@ -1529,22 +1531,22 @@ void ShellCorona::addOutput(QScreen *screen)
|
||||
#endif
|
||||
}
|
||||
|
||||
-void ShellCorona::checkAllDesktopsUiReady(bool ready)
|
||||
+void ShellCorona::checkAllDesktopsUiReady()
|
||||
{
|
||||
- if (!ready)
|
||||
+ const bool ready = std::ranges::all_of(std::as_const(m_desktopViewForScreen), [](const DesktopView *view) {
|
||||
+ return view->containment()->isUiReady();
|
||||
+ });
|
||||
+ if (!ready) {
|
||||
return;
|
||||
- for (auto v : std::as_const(m_desktopViewForScreen)) {
|
||||
- if (!v->containment()->isUiReady())
|
||||
- return;
|
||||
-
|
||||
- qCDebug(PLASMASHELL) << "Plasma Shell startup completed";
|
||||
- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"),
|
||||
- QStringLiteral("/KSplash"),
|
||||
- QStringLiteral("org.kde.KSplash"),
|
||||
- QStringLiteral("setStage"));
|
||||
- ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("desktop"));
|
||||
- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
|
||||
}
|
||||
+
|
||||
+ qCDebug(PLASMASHELL) << "Plasma Shell startup completed";
|
||||
+ QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"),
|
||||
+ QStringLiteral("/KSplash"),
|
||||
+ QStringLiteral("org.kde.KSplash"),
|
||||
+ QStringLiteral("setStage"));
|
||||
+ ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("desktop"));
|
||||
+ QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
|
||||
}
|
||||
|
||||
Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum)
|
||||
diff --git a/shell/shellcorona.h b/shell/shellcorona.h
|
||||
index 0f544ca266f..7b6c6a559a1 100644
|
||||
--- a/shell/shellcorona.h
|
||||
+++ b/shell/shellcorona.h
|
||||
@@ -275,7 +275,7 @@ private:
|
||||
DesktopView *desktopForScreen(QScreen *screen) const;
|
||||
void setupWaylandIntegration();
|
||||
void executeSetupPlasmoidScript(Plasma::Containment *containment, Plasma::Applet *applet);
|
||||
- void checkAllDesktopsUiReady(bool ready);
|
||||
+ void checkAllDesktopsUiReady();
|
||||
void activateLauncherMenu(const QString &screenName);
|
||||
void handleColorRequestedFromDBus(const QDBusMessage &msg);
|
||||
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 00bd19ecaccbb10d5cfcc6006b06a9714c615741 Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Wed, 25 Jun 2025 14:03:28 +0300
|
||||
Subject: [PATCH 2/2] shell: Create panel views after desktop views are ready
|
||||
|
||||
With the current code, the splash screen will be hidden as soon as the
|
||||
wallpapers are loaded.
|
||||
|
||||
However, the splash screnn is actually notified about the desktop stage
|
||||
about 1-1.5 second later after the wallpaper plugin resets the loading
|
||||
property.
|
||||
|
||||
The reason for that is that the panel is loaded between
|
||||
`wallpaper.loading = false` in the wallpaper and ShellCorona::checkAllDesktopsUiReady().
|
||||
|
||||
This change re-arranges the startup sequence so the panels are loaded
|
||||
after the desktop views become ready. It reduces plasma startup time a bit.
|
||||
|
||||
In long term, we should look for making panel loading as async as
|
||||
possible so the main thread doesn't get blocked for too long.
|
||||
---
|
||||
shell/shellcorona.cpp | 15 +++++----------
|
||||
1 file changed, 5 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp
|
||||
index 65c8ccc272e..6a59683dba7 100644
|
||||
--- a/shell/shellcorona.cpp
|
||||
+++ b/shell/shellcorona.cpp
|
||||
@@ -868,10 +868,6 @@ void ShellCorona::load()
|
||||
connect(m_screenPool, &ScreenPool::screenOrderChanged, this, &ShellCorona::handleScreenOrderChanged, Qt::UniqueConnection);
|
||||
connect(m_screenPool, &ScreenPool::screenRemoved, this, &ShellCorona::handleScreenRemoved, Qt::UniqueConnection);
|
||||
|
||||
- if (!m_waitingPanels.isEmpty()) {
|
||||
- m_waitingPanelsTimer.start();
|
||||
- }
|
||||
-
|
||||
if (config()->isImmutable() || !KAuthorized::authorize(QStringLiteral("plasma/plasmashell/unlockedDesktop"))) {
|
||||
setImmutability(Plasma::Types::SystemImmutable);
|
||||
} else {
|
||||
@@ -1517,11 +1513,6 @@ void ShellCorona::addOutput(QScreen *screen)
|
||||
// in the list. We still don't want to have an invisible view added.
|
||||
containment->reactToScreenChange();
|
||||
|
||||
- // were there any panels for this screen before it popped up?
|
||||
- if (!m_waitingPanels.isEmpty()) {
|
||||
- m_waitingPanelsTimer.start();
|
||||
- }
|
||||
-
|
||||
if (!m_screenReorderInProgress) {
|
||||
Q_EMIT availableScreenRectChanged(m_screenPool->idForScreen(screen));
|
||||
}
|
||||
@@ -1547,6 +1538,10 @@ void ShellCorona::checkAllDesktopsUiReady()
|
||||
QStringLiteral("setStage"));
|
||||
ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("desktop"));
|
||||
QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
|
||||
+
|
||||
+ if (!m_waitingPanels.isEmpty()) {
|
||||
+ m_waitingPanelsTimer.start();
|
||||
+ }
|
||||
}
|
||||
|
||||
Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum)
|
||||
@@ -1604,7 +1599,7 @@ void ShellCorona::createWaitingPanels()
|
||||
|
||||
QScreen *screen = m_screenPool->screenForId(requestedScreen);
|
||||
DesktopView *desktopView = desktopForScreen(screen);
|
||||
- if (!screen || !desktopView) {
|
||||
+ if (!screen || !desktopView || !desktopView->containment()->isUiReady()) {
|
||||
stillWaitingPanels << cont;
|
||||
continue;
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
||||
277
roles/kde/patches/plasma-workspace/pr5628.patch
Normal file
277
roles/kde/patches/plasma-workspace/pr5628.patch
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
From 9171f24afe6be37e1ac384b8ef03ff89b552be7a Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Wed, 25 Jun 2025 17:25:37 +0300
|
||||
Subject: [PATCH 1/2] startkde: Remove Before=plasma-ksplash-ready.service
|
||||
|
||||
This line makes ksplash wait for unrelated services such as powerdevil
|
||||
and baloo.
|
||||
|
||||
This change reduces plasma startup time on my machine to 2-3 seconds.
|
||||
---
|
||||
startkde/systemd/plasma-workspace.target | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target
|
||||
index a62db5e252a..a9113f49112 100644
|
||||
--- a/startkde/systemd/plasma-workspace.target
|
||||
+++ b/startkde/systemd/plasma-workspace.target
|
||||
@@ -17,7 +17,6 @@ Wants=xdg-desktop-autostart.target
|
||||
BindsTo=graphical-session.target
|
||||
Before=graphical-session.target
|
||||
Before=xdg-desktop-autostart.target
|
||||
-Before=plasma-ksplash-ready.service
|
||||
Before=plasma-restoresession.service
|
||||
RefuseManualStart=yes
|
||||
StopWhenUnneeded=true
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Wed, 25 Jun 2025 17:29:19 +0300
|
||||
Subject: [PATCH 2/2] startkde: Drop ready stage
|
||||
|
||||
In order to hide the splash screen, it is sufficient just to see the
|
||||
wallpaper. If more desktop environment components are loaded soon
|
||||
afterwards, it is okay.
|
||||
|
||||
With systemd boot, the way the ready stage is integrated is also kind
|
||||
of a hack.
|
||||
---
|
||||
appiumtests/CMakeLists.txt | 1 -
|
||||
appiumtests/ksplash/CMakeLists.txt | 14 ----
|
||||
appiumtests/ksplash/ksplashtest.py | 79 -------------------
|
||||
ksplash/ksplashqml/splashapp.cpp | 5 +-
|
||||
startkde/plasma-session/startup.cpp | 11 ---
|
||||
startkde/plasma-session/startup.h | 1 -
|
||||
startkde/systemd/CMakeLists.txt | 3 -
|
||||
.../systemd/plasma-ksplash-ready.service.in | 10 ---
|
||||
startkde/systemd/plasma-workspace.target | 1 -
|
||||
9 files changed, 2 insertions(+), 123 deletions(-)
|
||||
delete mode 100644 appiumtests/ksplash/CMakeLists.txt
|
||||
delete mode 100755 appiumtests/ksplash/ksplashtest.py
|
||||
delete mode 100644 startkde/systemd/plasma-ksplash-ready.service.in
|
||||
|
||||
diff --git a/appiumtests/CMakeLists.txt b/appiumtests/CMakeLists.txt
|
||||
index 68d0b6895ba..22234aeb031 100644
|
||||
--- a/appiumtests/CMakeLists.txt
|
||||
+++ b/appiumtests/CMakeLists.txt
|
||||
@@ -20,5 +20,4 @@ add_subdirectory(applets)
|
||||
add_subdirectory(components_tests)
|
||||
add_subdirectory(kcms)
|
||||
add_subdirectory(krunner)
|
||||
-add_subdirectory(ksplash)
|
||||
add_subdirectory(wallpapers)
|
||||
diff --git a/appiumtests/ksplash/CMakeLists.txt b/appiumtests/ksplash/CMakeLists.txt
|
||||
deleted file mode 100644
|
||||
index 3bea5174f5a..00000000000
|
||||
--- a/appiumtests/ksplash/CMakeLists.txt
|
||||
+++ /dev/null
|
||||
@@ -1,14 +0,0 @@
|
||||
-# SPDX-FileCopyrightText: 2024 Fushan Wen <qydwhotmail@gmail.com>
|
||||
-# SPDX-License-Identifier: BSD-3-Clause
|
||||
-
|
||||
-add_test(
|
||||
- NAME ksplashtest_wayland
|
||||
- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_wayland;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast"
|
||||
-)
|
||||
-set_tests_properties(ksplashtest_wayland PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_wayland;FLASK_PORT=5701")
|
||||
-
|
||||
-add_test(
|
||||
- NAME ksplashtest_x11
|
||||
- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_x11;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast"
|
||||
-)
|
||||
-set_tests_properties(ksplashtest_x11 PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_x11;FLASK_PORT=5702;TEST_WITH_KWIN_WAYLAND=0")
|
||||
diff --git a/appiumtests/ksplash/ksplashtest.py b/appiumtests/ksplash/ksplashtest.py
|
||||
deleted file mode 100755
|
||||
index b7ca43c0519..00000000000
|
||||
--- a/appiumtests/ksplash/ksplashtest.py
|
||||
+++ /dev/null
|
||||
@@ -1,79 +0,0 @@
|
||||
-#!/usr/bin/env python3
|
||||
-
|
||||
-# SPDX-FileCopyrightText: 2024 Fushan Wen <qydwhotmail@gmail.com>
|
||||
-# SPDX-License-Identifier: MIT
|
||||
-
|
||||
-# pylint: disable=too-many-arguments
|
||||
-
|
||||
-import os
|
||||
-import subprocess
|
||||
-import sys
|
||||
-import time
|
||||
-import unittest
|
||||
-
|
||||
-from appium import webdriver
|
||||
-from appium.options.common.base import AppiumOptions
|
||||
-from appium.webdriver.common.appiumby import AppiumBy
|
||||
-from gi.repository import Gio, GLib
|
||||
-
|
||||
-
|
||||
-class KSplashTest(unittest.TestCase):
|
||||
-
|
||||
- driver: webdriver.Remote
|
||||
-
|
||||
- @classmethod
|
||||
- def setUpClass(cls) -> None:
|
||||
- options = AppiumOptions()
|
||||
- options.set_capability("app", "ksplashqml --window")
|
||||
- options.set_capability("environ", {
|
||||
- "LC_ALL": "en_US.UTF-8",
|
||||
- "QT_FATAL_WARNINGS": "1",
|
||||
- "QT_LOGGING_RULES": "qt.accessibility.atspi.warning=false;kf.plasma.core.warning=false;kf.windowsystem.warning=false;kf.kirigami.platform.warning=false;org.kde.plasma.ksplashqml.debug=true",
|
||||
- })
|
||||
- options.set_capability("timeouts", {'implicit': 10000})
|
||||
- cls.driver = webdriver.Remote(command_executor=f'http://127.0.0.1:{os.getenv("FLASK_PORT", "4723")}', options=options)
|
||||
-
|
||||
- def tearDown(self) -> None:
|
||||
- """
|
||||
- Take screenshot when the current test fails
|
||||
- """
|
||||
- if not self._outcome.result.wasSuccessful():
|
||||
- self.driver.get_screenshot_as_file(f"failed_test_shot_ksplash_#{self.id()}.png")
|
||||
-
|
||||
- def test_1_bug494840_setStage(self) -> None:
|
||||
- """
|
||||
- Checks if the setStage method is ever called after starting plasma-ksplash-ready.service.
|
||||
- """
|
||||
- if os.getenv("TEST_WITH_KWIN_WAYLAND", "1") == "0":
|
||||
- stages = ("wm", "kcminit", "ksmserver", "startPlasma", "desktop")
|
||||
- else:
|
||||
- stages = ("kcminit", "ksmserver", "startPlasma", "desktop")
|
||||
-
|
||||
- session_bus = Gio.bus_get_sync(Gio.BusType.SESSION)
|
||||
- for stage in stages:
|
||||
- message: Gio.DBusMessage = Gio.DBusMessage.new_method_call("org.kde.KSplash", "/KSplash", "org.kde.KSplash", "setStage")
|
||||
- message.set_body(GLib.Variant("(s)", [stage]))
|
||||
- session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 3000)
|
||||
-
|
||||
- self.driver.find_element(AppiumBy.NAME, "Plasma made by KDE")
|
||||
-
|
||||
- with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "startkde", "systemd", "plasma-ksplash-ready.service.in"), encoding="utf-8") as handler:
|
||||
- for line in handler:
|
||||
- if line.startswith("ExecStart="):
|
||||
- command = line.removeprefix("ExecStart=").strip().split(" ")
|
||||
- subprocess.check_call(command, stdout=sys.stderr, stderr=sys.stderr)
|
||||
- break
|
||||
-
|
||||
- success = False
|
||||
- for _ in range(10):
|
||||
- try:
|
||||
- subprocess.check_call(["pidof", "ksplashqml"])
|
||||
- except subprocess.CalledProcessError:
|
||||
- success = True
|
||||
- break
|
||||
- time.sleep(1)
|
||||
- self.assertTrue(success)
|
||||
-
|
||||
-
|
||||
-if __name__ == '__main__':
|
||||
- unittest.main()
|
||||
diff --git a/ksplash/ksplashqml/splashapp.cpp b/ksplash/ksplashqml/splashapp.cpp
|
||||
index b60a58724be..2262503b1c3 100644
|
||||
--- a/ksplash/ksplashqml/splashapp.cpp
|
||||
+++ b/ksplash/ksplashqml/splashapp.cpp
|
||||
@@ -26,13 +26,12 @@
|
||||
#define TEST_STEP_INTERVAL 2000
|
||||
|
||||
/**
|
||||
- * There are 7 stages in ksplash
|
||||
+ * There are 6 stages in ksplash
|
||||
* - initial (from this class)
|
||||
* - startPlasma (from startplasma)
|
||||
* - kcminit
|
||||
* - ksmserver
|
||||
* - wm (for X11 from KWin, for Wayland from this class)
|
||||
- * - ready (from plasma-session startup)
|
||||
* - desktop (from shellcorona)
|
||||
*/
|
||||
|
||||
@@ -114,7 +113,7 @@ void SplashApp::setStage(const QString &stage)
|
||||
void SplashApp::setStage(int stage)
|
||||
{
|
||||
m_stage = stage;
|
||||
- if (m_stage == 7) {
|
||||
+ if (m_stage == 6) {
|
||||
QGuiApplication::exit(EXIT_SUCCESS);
|
||||
}
|
||||
for (SplashWindow *w : std::as_const(m_windows)) {
|
||||
diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp
|
||||
index a731c7b2791..0567e00881f 100644
|
||||
--- a/startkde/plasma-session/startup.cpp
|
||||
+++ b/startkde/plasma-session/startup.cpp
|
||||
@@ -206,20 +206,9 @@ Startup::Startup(QObject *parent)
|
||||
// app will be closed when all KJobs finish thanks to the QEventLoopLocker in each KJob
|
||||
}
|
||||
|
||||
-void Startup::upAndRunning(const QString &msg)
|
||||
-{
|
||||
- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"),
|
||||
- QStringLiteral("/KSplash"),
|
||||
- QStringLiteral("org.kde.KSplash"),
|
||||
- QStringLiteral("setStage"));
|
||||
- ksplashProgressMessage.setArguments(QList<QVariant>() << msg);
|
||||
- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
|
||||
-}
|
||||
-
|
||||
void Startup::finishStartup()
|
||||
{
|
||||
qCDebug(PLASMA_SESSION) << "Finished";
|
||||
- upAndRunning(QStringLiteral("ready"));
|
||||
|
||||
playStartupSound();
|
||||
new SessionTrack(m_processes);
|
||||
diff --git a/startkde/plasma-session/startup.h b/startkde/plasma-session/startup.h
|
||||
index 6ef4fee9bdd..876a1439fce 100644
|
||||
--- a/startkde/plasma-session/startup.h
|
||||
+++ b/startkde/plasma-session/startup.h
|
||||
@@ -20,7 +20,6 @@ class Startup : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
Startup(QObject *parent);
|
||||
- void upAndRunning(const QString &msg);
|
||||
void finishStartup();
|
||||
|
||||
static Startup *self()
|
||||
diff --git a/startkde/systemd/CMakeLists.txt b/startkde/systemd/CMakeLists.txt
|
||||
index 2f5d30e8456..c3455ebae81 100644
|
||||
--- a/startkde/systemd/CMakeLists.txt
|
||||
+++ b/startkde/systemd/CMakeLists.txt
|
||||
@@ -1,6 +1,3 @@
|
||||
-ecm_install_configured_files(INPUT plasma-ksplash-ready.service.in @ONLY
|
||||
- DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR})
|
||||
-
|
||||
install(FILES plasma-core.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR})
|
||||
install(FILES plasma-workspace.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR})
|
||||
install(FILES plasma-workspace-wayland.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR})
|
||||
diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in
|
||||
deleted file mode 100644
|
||||
index 1e903130a96..00000000000
|
||||
--- a/startkde/systemd/plasma-ksplash-ready.service.in
|
||||
+++ /dev/null
|
||||
@@ -1,10 +0,0 @@
|
||||
-[Unit]
|
||||
-Description=KSplash "ready" Stage
|
||||
-Wants=plasma-core.target
|
||||
-After=plasma-core.target
|
||||
-PartOf=graphical-session.target
|
||||
-
|
||||
-[Service]
|
||||
-Type=oneshot
|
||||
-ExecStart=dbus-send --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready
|
||||
-Slice=session.slice
|
||||
diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target
|
||||
index a9113f49112..4cc8d9330c3 100644
|
||||
--- a/startkde/systemd/plasma-workspace.target
|
||||
+++ b/startkde/systemd/plasma-workspace.target
|
||||
@@ -6,7 +6,6 @@ Wants=plasma-restoresession.service
|
||||
Wants=plasma-xembedsniproxy.service
|
||||
Wants=plasma-gmenudbusmenuproxy.service
|
||||
Wants=plasma-powerdevil.service
|
||||
-Wants=plasma-ksplash-ready.service
|
||||
Wants=plasma-polkit-agent.service
|
||||
Wants=kde-baloo.service
|
||||
Wants=plasma-foreground-booster.service
|
||||
--
|
||||
GitLab
|
||||
|
||||
3
roles/kde/patches/spectacle/patches.txt
Normal file
3
roles/kde/patches/spectacle/patches.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Plasma 6.5.0:
|
||||
|
||||
Pr 460 https://invent.kde.org/plasma/spectacle/-/merge_requests/460
|
||||
228
roles/kde/patches/spectacle/pr460.patch
Normal file
228
roles/kde/patches/spectacle/pr460.patch
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
From 97f209559c00acc1ea6d0736bb318ac0254a3e37 Mon Sep 17 00:00:00 2001
|
||||
From: Noah Davis <noahadvs@gmail.com>
|
||||
Date: Wed, 4 Jun 2025 16:06:06 -0400
|
||||
Subject: [PATCH 1/2] Say which shortcut can stop recording in recording
|
||||
notification
|
||||
|
||||
It will say Meta+R by default, but will show the shortcut used to initiate the recording instead if Meta+R isn't assigned to region recording.
|
||||
|
||||
BUG: 505081
|
||||
---
|
||||
src/Platforms/VideoPlatform.cpp | 16 +++++++++++++++
|
||||
src/Platforms/VideoPlatform.h | 4 ++++
|
||||
src/Platforms/VideoPlatformWayland.cpp | 6 ++++--
|
||||
src/SpectacleCore.cpp | 28 +++++++++++++++++++++++++-
|
||||
4 files changed, 51 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/Platforms/VideoPlatform.cpp b/src/Platforms/VideoPlatform.cpp
|
||||
index 592539048..333692326 100644
|
||||
--- a/src/Platforms/VideoPlatform.cpp
|
||||
+++ b/src/Platforms/VideoPlatform.cpp
|
||||
@@ -69,6 +69,11 @@ VideoPlatform::RecordingState VideoPlatform::recordingState() const
|
||||
return m_recordingState;
|
||||
}
|
||||
|
||||
+VideoPlatform::RecordingMode VideoPlatform::recordingMode() const
|
||||
+{
|
||||
+ return m_recordingMode;
|
||||
+}
|
||||
+
|
||||
void VideoPlatform::setRecordingState(RecordingState state)
|
||||
{
|
||||
if (state == m_recordingState) {
|
||||
@@ -91,9 +96,20 @@ void VideoPlatform::setRecordingState(RecordingState state)
|
||||
m_elapsedTimer.invalidate();
|
||||
m_basicTimer.stop();
|
||||
}
|
||||
+ if (state != RecordingState::Recording) {
|
||||
+ setRecordingMode(NoRecordingModes);
|
||||
+ }
|
||||
m_recordingState = state;
|
||||
Q_EMIT recordingStateChanged(state);
|
||||
Q_EMIT recordedTimeChanged();
|
||||
}
|
||||
|
||||
+void VideoPlatform::setRecordingMode(RecordingMode mode)
|
||||
+{
|
||||
+ if (m_recordingMode == mode) {
|
||||
+ return;
|
||||
+ }
|
||||
+ m_recordingMode = mode;
|
||||
+}
|
||||
+
|
||||
#include "moc_VideoPlatform.cpp"
|
||||
diff --git a/src/Platforms/VideoPlatform.h b/src/Platforms/VideoPlatform.h
|
||||
index 4f5fba720..eea81e32a 100644
|
||||
--- a/src/Platforms/VideoPlatform.h
|
||||
+++ b/src/Platforms/VideoPlatform.h
|
||||
@@ -129,8 +129,11 @@ public:
|
||||
|
||||
RecordingState recordingState() const;
|
||||
|
||||
+ RecordingMode recordingMode() const;
|
||||
+
|
||||
protected:
|
||||
void setRecordingState(RecordingState state);
|
||||
+ void setRecordingMode(RecordingMode mode);
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
@@ -157,6 +160,7 @@ private:
|
||||
QBasicTimer m_basicTimer;
|
||||
qint64 m_recordedTime = 0;
|
||||
RecordingState m_recordingState = RecordingState::NotRecording;
|
||||
+ RecordingMode m_recordingMode = RecordingMode::NoRecordingModes;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(VideoPlatform::RecordingModes)
|
||||
diff --git a/src/Platforms/VideoPlatformWayland.cpp b/src/Platforms/VideoPlatformWayland.cpp
|
||||
index 648f8adbf..984ede0eb 100644
|
||||
--- a/src/Platforms/VideoPlatformWayland.cpp
|
||||
+++ b/src/Platforms/VideoPlatformWayland.cpp
|
||||
@@ -245,11 +245,12 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec
|
||||
m_recorder->setNodeId(0);
|
||||
|
||||
Q_ASSERT(stream);
|
||||
- connect(stream, &ScreencastingStream::created, this, [this, stream] {
|
||||
+ connect(stream, &ScreencastingStream::created, this, [this, stream, recordingMode] {
|
||||
m_recorder->setNodeId(stream->nodeId());
|
||||
if (!m_recorder->output().isEmpty()) {
|
||||
m_recorder->start();
|
||||
}
|
||||
+ setRecordingMode(recordingMode);
|
||||
setRecordingState(VideoPlatform::RecordingState::Recording);
|
||||
});
|
||||
connect(stream, &ScreencastingStream::failed, this, [this](const QString &error) {
|
||||
@@ -302,7 +303,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec
|
||||
m_recorder->start();
|
||||
}
|
||||
|
||||
- connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this] {
|
||||
+ connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this, recordingMode] {
|
||||
if (m_recorder->state() == PipeWireRecord::Idle) {
|
||||
m_memoryTimer.stop();
|
||||
if (recordingState() != RecordingState::NotRecording && recordingState() != RecordingState::Finished) {
|
||||
@@ -311,6 +312,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec
|
||||
}
|
||||
} else if (m_recorder->state() == PipeWireRecord::Recording) {
|
||||
m_memoryTimer.start(5000, Qt::CoarseTimer, this);
|
||||
+ setRecordingMode(recordingMode);
|
||||
setRecordingState(VideoPlatform::RecordingState::Recording);
|
||||
} else if (m_recorder->state() == PipeWireRecord::Rendering) {
|
||||
m_memoryTimer.stop();
|
||||
diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp
|
||||
index 8033751c9..aa2e8c6e1 100644
|
||||
--- a/src/SpectacleCore.cpp
|
||||
+++ b/src/SpectacleCore.cpp
|
||||
@@ -281,7 +281,33 @@ SpectacleCore::SpectacleCore(QObject *parent)
|
||||
SpectacleCore::instance()->finishRecording();
|
||||
});
|
||||
const auto messageTitle = i18nc("recording notification title", "Spectacle is Recording");
|
||||
- const auto messageBody = i18nc("recording notification message", "Click the system tray icon to finish recording");
|
||||
+ auto getSimpleDefaultShortcut = [] {
|
||||
+ const auto shortcuts = KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction());
|
||||
+ if (shortcuts.contains(QKeySequence{Qt::META | Qt::Key_R})) {
|
||||
+ return QKeySequence{Qt::META | Qt::Key_R};
|
||||
+ }
|
||||
+ return QKeySequence{};
|
||||
+ };
|
||||
+ auto getShortcut = [](const auto &list) {
|
||||
+ auto it = std::find_if(list.cbegin(), list.cend(), [](const QKeySequence &shortcut) {
|
||||
+ return !shortcut.isEmpty();
|
||||
+ });
|
||||
+ return it != list.cend() ? *it : QKeySequence{};
|
||||
+ };
|
||||
+ QKeySequence stopShortcut = getSimpleDefaultShortcut();
|
||||
+ if (stopShortcut.isEmpty()) {
|
||||
+ auto mode = m_videoPlatform->recordingMode();
|
||||
+ if (mode == VideoPlatform::Screen) {
|
||||
+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordScreenAction()));
|
||||
+ } else if (mode == VideoPlatform::Window) {
|
||||
+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordWindowAction()));
|
||||
+ } else if (mode == VideoPlatform::Region) {
|
||||
+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction()));
|
||||
+ }
|
||||
+ }
|
||||
+ const auto messageBody = stopShortcut.isEmpty()
|
||||
+ ? i18nc("recording notification message without shortcut", "To finish the recording, click the pulsing red System Tray icon.")
|
||||
+ : xi18nc("recording notification message with shortcut", "To finish the recording, click the pulsing red System Tray icon or press <shortcut>%1</shortcut>.", stopShortcut.toString(QKeySequence::NativeText));
|
||||
auto notification = new KNotification(u"notification"_s, KNotification::CloseOnTimeout | KNotification::DefaultEvent, this);
|
||||
notification->setTitle(messageTitle);
|
||||
notification->setText(messageBody);
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
From 7fd2fe158408b6285f9855f7fcf34e77d4ecb764 Mon Sep 17 00:00:00 2001
|
||||
From: Noah Davis <noahadvs@gmail.com>
|
||||
Date: Thu, 12 Jun 2025 16:12:48 -0400
|
||||
Subject: [PATCH 2/2] Rename shortcuts to show that they can start or stop
|
||||
recording
|
||||
|
||||
BUG: 505081
|
||||
---
|
||||
desktop/org.kde.spectacle.desktop.cmake | 6 +++---
|
||||
src/ShortcutActions.cpp | 6 +++---
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/desktop/org.kde.spectacle.desktop.cmake b/desktop/org.kde.spectacle.desktop.cmake
|
||||
index 4e36b18e6..800fcb62b 100644
|
||||
--- a/desktop/org.kde.spectacle.desktop.cmake
|
||||
+++ b/desktop/org.kde.spectacle.desktop.cmake
|
||||
@@ -474,7 +474,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -u
|
||||
X-KDE-Shortcuts=Meta+Ctrl+Print
|
||||
|
||||
[Desktop Action RecordRegion]
|
||||
-Name=Record Rectangular Region
|
||||
+Name=Start/Stop Region Recording
|
||||
Name[ar]=يسجل منطقة مستطيلة
|
||||
Name[az]=Düzbucaqlı sahəni yazmaq
|
||||
Name[bg]=Заснемане на правоъгълен регион
|
||||
@@ -522,7 +522,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R region
|
||||
X-KDE-Shortcuts=Meta+Shift+R,Meta+R
|
||||
|
||||
[Desktop Action RecordScreen]
|
||||
-Name=Record Screen
|
||||
+Name=Start/Stop Screen Recording
|
||||
Name[ar]=سجّل الشاشة
|
||||
Name[az]=Ekranı yazmaq
|
||||
Name[bg]=Запис на екрана
|
||||
@@ -570,7 +570,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R screen
|
||||
X-KDE-Shortcuts=Meta+Alt+R
|
||||
|
||||
[Desktop Action RecordWindow]
|
||||
-Name=Record Window
|
||||
+Name=Start/Stop Window Recording
|
||||
Name[ar]=سجل النافذة
|
||||
Name[az]=Pəncərəni yazmaq
|
||||
Name[bg]=Запис на прозорец
|
||||
diff --git a/src/ShortcutActions.cpp b/src/ShortcutActions.cpp
|
||||
index ee73bcfe5..a1464d06d 100644
|
||||
--- a/src/ShortcutActions.cpp
|
||||
+++ b/src/ShortcutActions.cpp
|
||||
@@ -73,19 +73,19 @@ ShortcutActions::ShortcutActions()
|
||||
mActions.addAction(action->objectName(), action);
|
||||
}
|
||||
{
|
||||
- QAction *action = new QAction(i18nc("@action global shortcut", "Record Screen"), &mActions);
|
||||
+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Screen Recording"), &mActions);
|
||||
action->setObjectName(u"RecordScreen"_s);
|
||||
action->setProperty("isConfigurationAction", true);
|
||||
mActions.addAction(action->objectName(), action);
|
||||
}
|
||||
{
|
||||
- QAction *action = new QAction(i18nc("@action global shortcut", "Record Window"), &mActions);
|
||||
+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Window Recording"), &mActions);
|
||||
action->setObjectName(u"RecordWindow"_s);
|
||||
action->setProperty("isConfigurationAction", true);
|
||||
mActions.addAction(action->objectName(), action);
|
||||
}
|
||||
{
|
||||
- QAction *action = new QAction(i18nc("@action global shortcut", "Record Rectangular Region"), &mActions);
|
||||
+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Region Recording"), &mActions);
|
||||
action->setObjectName(u"RecordRegion"_s);
|
||||
action->setProperty("isConfigurationAction", true);
|
||||
mActions.addAction(action->objectName(), action);
|
||||
--
|
||||
GitLab
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue