Skip to content

Commit 68694ac

Browse files
feat(keybind-cheatsheet): v3.5.0 — full color customization, clipboard paste, and new pill UI
- Every key category gets both bg + text color pickers (Super/Ctrl/Shift/Alt/XF86/Print/Numeric/Mouse/Default). - Modifier-key bg empty = Noctalia theme accent (mPrimary/mSecondary/mTertiary), stays theme-aware. - Redesigned picker row: two compact pills (bg + text-with-letter-preview) sized to hex width; pencil icon removed. - Clipboard quick-paste: copy any hex color anywhere and a clipboard icon appears in the pill for one-click paste (wl-paste polled while Settings visible). - Panel now follows Noctalia panel-opacity rules (panel-in-panel semi-translucent background, matches tailscale/hello-world). - Fixed WARN on Color.mPrimaryContainer (replaced with mPrimary/mSecondary/mTertiary). - Extracted reusable ColorPill.qml and ColorPairRow.qml components. - Added settings.color-auto and settings.color-paste-hint i18n keys across all 20 languages (localized for major locales, EN fallback elsewhere).
1 parent 48c7b9b commit 68694ac

29 files changed

Lines changed: 3458 additions & 1843 deletions

keybind-cheatsheet/BarWidget.qml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ NIconButton {
1111
property ShellScreen screen
1212
property string widgetId: ""
1313
property string section: ""
14+
property int sectionWidgetIndex: -1
15+
property int sectionWidgetsCount: 0
1416

1517
baseSize: Style.getCapsuleHeightForScreen(screen?.name)
1618
applyUiScale: false
1719
icon: "keyboard"
18-
tooltipText: pluginApi?.tr("keybind-cheatsheet.barwidget.tooltip") || "Keybind Cheatsheet"
20+
tooltipText: pluginApi?.tr("barwidget.tooltip")
1921
tooltipDirection: BarService.getTooltipDirection(screen?.name)
2022
customRadius: Style.radiusL
2123

@@ -34,12 +36,12 @@ NIconButton {
3436

3537
model: [
3638
{
37-
"label": "Open Cheatsheet",
39+
"label": pluginApi?.tr("barwidget.open"),
3840
"action": "open-panel",
3941
"icon": "keyboard"
4042
},
4143
{
42-
"label": "Plugin Settings",
44+
"label": pluginApi?.tr("barwidget.settings"),
4345
"action": "plugin-settings",
4446
"icon": "settings"
4547
},

keybind-cheatsheet/CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
# Changelog
22

3+
## [3.5.0] - 2026-04-21
4+
5+
### ✨ Features
6+
7+
**Full Per-Category Color Customization**
8+
- Every key category (Super, Ctrl, Shift, Alt, XF86, Print, Numeric, Mouse, Default) now has **both** a background-color and a text-color picker.
9+
- Description text color is also independently customizable.
10+
- Empty background for modifier keys (Super / Ctrl / Shift) falls back to the current Noctalia theme accent colors (mPrimary / mSecondary / mTertiary), so the plugin stays theme-aware out of the box.
11+
- Empty text overrides fall back to the global "Key label" color.
12+
13+
**Redesigned Color Picker UI**
14+
- Replaced label + single pencil button with a compact two-pill layout per category: left pill = background (colored circle + hex), right pill = text (circle with letter preview in the selected text color + hex).
15+
- Clicking anywhere on a pill opens the color picker dialog — the pencil icon is gone; clickability is obvious from the interactive hover state.
16+
- Pills are sized to the hex-code width for a tight, scannable layout.
17+
18+
**Clipboard Quick-Paste**
19+
- Copy any hex color (e.g. `#FF6B6B`) anywhere on your system and a clipboard icon appears inside each pill for one-click paste.
20+
- Wayland clipboard is polled via `wl-paste` every 1.5s while the Settings panel is visible; polling stops automatically on close.
21+
- Accepted formats: `#RRGGBB`, `#RRGGBBAA`, or the same without the leading `#`.
22+
- A hint with a clipboard icon above the pickers explains the feature; the icon highlights in the theme accent when a valid hex is on the clipboard.
23+
24+
**Panel Opacity Consistency**
25+
- The panel now follows Noctalia's global panel-opacity rules (same pattern as the `tailscale` and `hello-world` plugins) — content sits inside a panel-within-panel with the semi-translucent background from the theme.
26+
27+
### 🐛 Bug Fixes
28+
29+
- Fixed `WARN scene … Unable to assign [undefined] to QColor` caused by referencing a non-existent `Color.mPrimaryContainer` symbol; modifier-key fallbacks now use `Color.mPrimary / mSecondary / mTertiary`.
30+
31+
### 🌍 Translations
32+
33+
- Added `settings.color-auto` (pill placeholder) and `settings.color-paste-hint` (clipboard instructions) to all 20 supported language files.
34+
- Localized both keys for JA / ZH-CN / ZH-TW / KO-KR / RU / UK-UA / PL / DE / ES / FR / IT / PT / NL / TR / HU / SV / NN-NO / KU / HN; English fallback kept for remaining languages.
35+
36+
### 🔧 Code Quality
37+
38+
- Extracted reusable `ColorPill.qml` and `ColorPairRow.qml` components; Settings.qml color-picker section went from 11 hand-rolled RowLayouts to 10 declarative rows.
39+
- Unified all color value properties as `string` (previously mixed `color` / `string`) so the empty-string fallback sentinel works uniformly.
40+
- Live-preview + revert-on-cancel: color edits apply instantly, snapshot restored on close if Apply was never pressed.
41+
- Clipboard Timer + Process are properly stopped in `Component.onDestruction`.
42+
43+
---
44+
345
## [3.2.2] - 2026-02-08
446

547
### 🐛 Bug Fixes
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import QtQuick
2+
import QtQuick.Controls
3+
import QtQuick.Layouts
4+
import qs.Commons
5+
import qs.Widgets
6+
7+
// Label + background pill + text pill + reset. Used by Settings.qml for per-category
8+
// color customization. Empty bgValue/textValue means "use fallback".
9+
RowLayout {
10+
id: row
11+
12+
property var pluginApi
13+
property var screen
14+
property string labelText: ""
15+
property string bgValue: ""
16+
property string textValue: ""
17+
property color bgFallback: "#888888"
18+
property color textFallback: "#FFFFFF"
19+
property string letter: "A"
20+
property string clipboardHex: ""
21+
property bool showBg: true
22+
property bool showText: true
23+
24+
signal bgPicked(color value)
25+
signal textPicked(color value)
26+
signal bgPasted(string hex)
27+
signal textPasted(string hex)
28+
signal resetRequested()
29+
30+
Layout.fillWidth: true
31+
spacing: Style.marginM
32+
33+
NText {
34+
text: row.labelText
35+
color: Color.mOnSurface
36+
pointSize: Style.fontSizeM
37+
Layout.preferredWidth: 180 * Style.uiScaleRatio
38+
elide: Text.ElideRight
39+
}
40+
41+
ColorPill {
42+
Layout.preferredWidth: 130 * Style.uiScaleRatio
43+
visible: row.showBg
44+
screen: row.screen
45+
hexValue: row.bgValue
46+
displayColor: row.bgValue.length > 0 ? row.bgValue : row.bgFallback
47+
textMode: false
48+
clipboardHex: row.clipboardHex
49+
placeholderText: row.bgValue.length === 0 ? (row.pluginApi?.tr("settings.color-auto") || "auto") : ""
50+
onColorPicked: c => row.bgPicked(c)
51+
onPasteRequested: hex => row.bgPasted(hex)
52+
}
53+
54+
ColorPill {
55+
Layout.preferredWidth: 130 * Style.uiScaleRatio
56+
visible: row.showText
57+
screen: row.screen
58+
hexValue: row.textValue
59+
displayColor: row.textValue.length > 0 ? row.textValue : row.textFallback
60+
textMode: true
61+
letter: row.letter
62+
textModeBg: row.bgValue.length > 0 ? row.bgValue : row.bgFallback
63+
clipboardHex: row.clipboardHex
64+
placeholderText: row.textValue.length === 0 ? (row.pluginApi?.tr("settings.color-auto") || "auto") : ""
65+
onColorPicked: c => row.textPicked(c)
66+
onPasteRequested: hex => row.textPasted(hex)
67+
}
68+
69+
Item { Layout.fillWidth: true }
70+
71+
NIconButton {
72+
icon: "rotate"
73+
tooltipText: row.pluginApi?.tr("settings.reset-color")
74+
onClicked: row.resetRequested()
75+
}
76+
}

keybind-cheatsheet/ColorPill.qml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import QtQuick
2+
import QtQuick.Controls
3+
import QtQuick.Layouts
4+
import qs.Commons
5+
import qs.Widgets
6+
7+
// Compact color pill: circle + hex code + optional paste icon.
8+
// Opens NColorPickerDialog on click. Used in pairs (bg + text) per keybind category.
9+
Rectangle {
10+
id: pill
11+
12+
property var screen
13+
property string hexValue: ""
14+
property color displayColor: "#888888"
15+
property bool textMode: false
16+
property string letter: "A"
17+
property color textModeBg: "#444444"
18+
property string clipboardHex: ""
19+
property string placeholderText: ""
20+
21+
signal colorPicked(color value)
22+
signal pasteRequested(string hex)
23+
24+
readonly property bool hasClipboardColor: clipboardHex.length > 0 &&
25+
clipboardHex.toLowerCase() !== hexValue.toLowerCase()
26+
27+
implicitWidth: 150
28+
implicitHeight: Math.round(Style.baseWidgetSize * 1.1)
29+
30+
radius: Style.iRadiusM
31+
color: Color.mSurface
32+
border.color: mouseArea.containsMouse ? Color.mPrimary : Color.mOutline
33+
border.width: Style.borderS
34+
35+
MouseArea {
36+
id: mouseArea
37+
anchors.fill: parent
38+
hoverEnabled: true
39+
cursorShape: Qt.PointingHandCursor
40+
onClicked: {
41+
var startColor = pill.hexValue.length > 0 ? pill.hexValue : pill.displayColor;
42+
var dialog = dialogFactory.createObject(Overlay.overlay, {
43+
"selectedColor": startColor,
44+
"screen": pill.screen
45+
});
46+
if (!dialog) return;
47+
dialog.colorSelected.connect(function(c) {
48+
pill.colorPicked(c);
49+
});
50+
dialog.open();
51+
}
52+
}
53+
54+
Component {
55+
id: dialogFactory
56+
NColorPickerDialog {}
57+
}
58+
59+
RowLayout {
60+
anchors.fill: parent
61+
anchors.leftMargin: Style.marginS
62+
anchors.rightMargin: Style.marginS
63+
spacing: Style.marginS
64+
65+
Rectangle {
66+
Layout.preferredWidth: pill.height * 0.62
67+
Layout.preferredHeight: pill.height * 0.62
68+
radius: width / 2
69+
color: pill.textMode ? pill.textModeBg : pill.displayColor
70+
border.color: Color.mOutline
71+
border.width: Style.borderS
72+
73+
NText {
74+
anchors.centerIn: parent
75+
visible: pill.textMode
76+
text: pill.letter
77+
color: pill.displayColor
78+
font.weight: Style.fontWeightBold
79+
pointSize: Style.fontSizeS
80+
}
81+
}
82+
83+
NText {
84+
Layout.fillWidth: true
85+
Layout.alignment: Qt.AlignVCenter
86+
text: pill.hexValue.length > 0
87+
? pill.hexValue.toUpperCase()
88+
: (pill.placeholderText.length > 0 ? pill.placeholderText : "auto")
89+
family: Settings.data.ui.fontFixed
90+
color: pill.hexValue.length > 0 ? Color.mOnSurface : Color.mOnSurfaceVariant
91+
pointSize: Style.fontSizeXS
92+
elide: Text.ElideRight
93+
}
94+
95+
Rectangle {
96+
Layout.preferredWidth: pill.height * 0.62
97+
Layout.preferredHeight: pill.height * 0.62
98+
visible: pill.hasClipboardColor
99+
radius: width / 2
100+
color: pasteArea.containsMouse ? Color.mPrimary : Color.mSurfaceVariant
101+
border.color: Color.mOutline
102+
border.width: Style.borderS
103+
104+
NIcon {
105+
anchors.centerIn: parent
106+
icon: "clipboard"
107+
color: pasteArea.containsMouse ? Color.mOnPrimary : Color.mOnSurfaceVariant
108+
pointSize: Style.fontSizeS
109+
}
110+
111+
MouseArea {
112+
id: pasteArea
113+
anchors.fill: parent
114+
hoverEnabled: true
115+
cursorShape: Qt.PointingHandCursor
116+
onClicked: pill.pasteRequested(pill.clipboardHex)
117+
}
118+
119+
ToolTip.visible: pasteArea.containsMouse && pill.clipboardHex.length > 0
120+
ToolTip.text: pill.clipboardHex.toUpperCase()
121+
ToolTip.delay: 400
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)