forked from Shinonome/dots-hyprland
custom system tray
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import qs.modules.common
|
import qs.modules.common
|
||||||
|
import qs.modules.common.widgets
|
||||||
import qs.modules.common.functions
|
import qs.modules.common.functions
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
@@ -26,6 +27,10 @@ LazyLoader {
|
|||||||
implicitWidth: popupBackground.implicitWidth + Appearance.sizes.hyprlandGapsOut * 2 + root.popupBackgroundMargin
|
implicitWidth: popupBackground.implicitWidth + Appearance.sizes.hyprlandGapsOut * 2 + root.popupBackgroundMargin
|
||||||
implicitHeight: popupBackground.implicitHeight + Appearance.sizes.hyprlandGapsOut * 2 + root.popupBackgroundMargin
|
implicitHeight: popupBackground.implicitHeight + Appearance.sizes.hyprlandGapsOut * 2 + root.popupBackgroundMargin
|
||||||
|
|
||||||
|
mask: Region {
|
||||||
|
item: popupBackground
|
||||||
|
}
|
||||||
|
|
||||||
exclusionMode: ExclusionMode.Ignore
|
exclusionMode: ExclusionMode.Ignore
|
||||||
exclusiveZone: 0
|
exclusiveZone: 0
|
||||||
margins {
|
margins {
|
||||||
@@ -49,15 +54,8 @@ LazyLoader {
|
|||||||
WlrLayershell.namespace: "quickshell:popup"
|
WlrLayershell.namespace: "quickshell:popup"
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
WlrLayershell.layer: WlrLayer.Overlay
|
||||||
|
|
||||||
RectangularShadow {
|
StyledRectangularShadow {
|
||||||
property var target: popupBackground
|
target: popupBackground
|
||||||
anchors.fill: target
|
|
||||||
radius: target.radius
|
|
||||||
blur: 0.9 * Appearance.sizes.hyprlandGapsOut
|
|
||||||
offset: Qt.vector2d(0.0, 1.0)
|
|
||||||
spread: 0.7
|
|
||||||
color: Appearance.colors.colShadow
|
|
||||||
cached: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import qs.modules.common.widgets
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -14,20 +15,58 @@ Item {
|
|||||||
property bool trayOverflowOpen: false
|
property bool trayOverflowOpen: false
|
||||||
property bool showSeparator: true
|
property bool showSeparator: true
|
||||||
property bool showOverflowMenu: true
|
property bool showOverflowMenu: true
|
||||||
|
property var activeMenu: null
|
||||||
|
|
||||||
property list<var> itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && i.status !== Status.Passive))
|
property list<var> itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && i.status !== Status.Passive))
|
||||||
property list<var> itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && i.status !== Status.Passive))
|
property list<var> itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && i.status !== Status.Passive))
|
||||||
property bool invertPins: Config.options.bar.tray.invertPinnedItems
|
property bool invertPins: Config.options.bar.tray.invertPinnedItems
|
||||||
property list<var> pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
|
property list<var> pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
|
||||||
property list<var> unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
|
property list<var> unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
|
||||||
onUnpinnedItemsChanged: if (unpinnedItems.length == 0)
|
onUnpinnedItemsChanged: {
|
||||||
root.trayOverflowOpen = false
|
if (unpinnedItems.length == 0) root.closeOverflowMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
function grabFocus() {
|
||||||
|
focusGrab.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setExtraWindowAndGrabFocus(window) {
|
||||||
|
root.activeMenu = window;
|
||||||
|
root.grabFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseFocus() {
|
||||||
|
focusGrab.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeOverflowMenu() {
|
||||||
|
focusGrab.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onTrayOverflowOpenChanged: {
|
||||||
|
if (root.trayOverflowOpen) {
|
||||||
|
root.grabFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab {
|
||||||
|
id: focusGrab
|
||||||
|
active: false
|
||||||
|
windows: [trayOverflowLayout.QsWindow?.window, root.activeMenu]
|
||||||
|
onCleared: {
|
||||||
|
root.trayOverflowOpen = false;
|
||||||
|
if (root.activeMenu) {
|
||||||
|
root.activeMenu.close();
|
||||||
|
root.activeMenu = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
id: gridLayout
|
id: gridLayout
|
||||||
columns: root.vertical ? 1 : -1
|
columns: root.vertical ? 1 : -1
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
rowSpacing: 6
|
rowSpacing: 8
|
||||||
columnSpacing: 15
|
columnSpacing: 15
|
||||||
|
|
||||||
RippleButton {
|
RippleButton {
|
||||||
@@ -60,6 +99,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledPopup {
|
StyledPopup {
|
||||||
|
id: overflowPopup
|
||||||
hoverTarget: trayOverflowButton
|
hoverTarget: trayOverflowButton
|
||||||
active: root.trayOverflowOpen
|
active: root.trayOverflowOpen
|
||||||
popupBackgroundMargin: 300 // This should be plenty... makes sure tooltips don't get cutoff (easily)
|
popupBackgroundMargin: 300 // This should be plenty... makes sure tooltips don't get cutoff (easily)
|
||||||
@@ -79,6 +119,8 @@ Item {
|
|||||||
item: modelData
|
item: modelData
|
||||||
Layout.fillHeight: !root.vertical
|
Layout.fillHeight: !root.vertical
|
||||||
Layout.fillWidth: root.vertical
|
Layout.fillWidth: root.vertical
|
||||||
|
onMenuClosed: root.releaseFocus();
|
||||||
|
onMenuOpened: (qsWindow) => root.setExtraWindowAndGrabFocus(qsWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,6 +137,10 @@ Item {
|
|||||||
item: modelData
|
item: modelData
|
||||||
Layout.fillHeight: !root.vertical
|
Layout.fillHeight: !root.vertical
|
||||||
Layout.fillWidth: root.vertical
|
Layout.fillWidth: root.vertical
|
||||||
|
onMenuClosed: root.releaseFocus();
|
||||||
|
onMenuOpened: (qsWindow) => {
|
||||||
|
root.setExtraWindowAndGrabFocus(qsWindow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ import Qt5Compat.GraphicalEffects
|
|||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var bar: root.QsWindow.window
|
|
||||||
required property SystemTrayItem item
|
required property SystemTrayItem item
|
||||||
property bool targetMenuOpen: false
|
property bool targetMenuOpen: false
|
||||||
hoverEnabled: true
|
|
||||||
|
|
||||||
|
signal menuOpened(qsWindow: var)
|
||||||
|
signal menuClosed()
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
implicitWidth: 20
|
implicitWidth: 20
|
||||||
implicitHeight: 20
|
implicitHeight: 20
|
||||||
@@ -36,16 +37,30 @@ MouseArea {
|
|||||||
if (Config.options.bar.tray.showItemId) tooltip.content += "\n[" + item.id + "]";
|
if (Config.options.bar.tray.showItemId) tooltip.content += "\n[" + item.id + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
QsMenuAnchor {
|
Loader {
|
||||||
id: menu
|
id: menu
|
||||||
|
function open() {
|
||||||
menu: root.item.menu
|
menu.active = true;
|
||||||
anchor.window: bar
|
}
|
||||||
anchor.rect.x: root.x + (Config.options.bar.vertical ? 0 : bar?.width)
|
active: false
|
||||||
anchor.rect.y: root.y + (Config.options.bar.vertical ? bar?.height : 0)
|
sourceComponent: SysTrayMenu {
|
||||||
anchor.rect.height: root.height
|
Component.onCompleted: this.open();
|
||||||
anchor.rect.width: root.width
|
trayItemMenuHandle: root.item.menu
|
||||||
anchor.edges: Config.options.bar.bottom ? (Edges.Top | Edges.Left) : (Edges.Bottom | Edges.Right)
|
anchor {
|
||||||
|
window: root.QsWindow.window
|
||||||
|
rect.x: root.x + (Config.options.bar.vertical ? 0 : QsWindow.window?.width)
|
||||||
|
rect.y: root.y + (Config.options.bar.vertical ? QsWindow.window?.height : 0)
|
||||||
|
rect.height: root.height
|
||||||
|
rect.width: root.width
|
||||||
|
edges: Config.options.bar.bottom ? (Edges.Top | Edges.Left) : (Edges.Bottom | Edges.Right)
|
||||||
|
gravity: Config.options.bar.bottom ? (Edges.Top | Edges.Left) : (Edges.Bottom | Edges.Right)
|
||||||
|
}
|
||||||
|
onMenuOpened: (window) => root.menuOpened(window);
|
||||||
|
onMenuClosed: {
|
||||||
|
root.menuClosed();
|
||||||
|
menu.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import qs
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.widgets
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
|
||||||
|
PopupWindow {
|
||||||
|
id: root
|
||||||
|
required property QsMenuHandle trayItemMenuHandle
|
||||||
|
property real popupBackgroundMargin: 0
|
||||||
|
|
||||||
|
signal menuClosed
|
||||||
|
signal menuOpened(qsWindow: var) // Correct type is QsWindow, but QML does not like that
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
property real padding: Appearance.sizes.elevationMargin
|
||||||
|
|
||||||
|
implicitHeight: {
|
||||||
|
let result = 0;
|
||||||
|
for (let child of stackView.children) {
|
||||||
|
result = Math.max(child.implicitHeight, result);
|
||||||
|
}
|
||||||
|
return result + popupBackground.padding * 2 + root.padding * 2;
|
||||||
|
}
|
||||||
|
implicitWidth: {
|
||||||
|
let result = 0;
|
||||||
|
for (let child of stackView.children) {
|
||||||
|
result = Math.max(child.implicitWidth, result);
|
||||||
|
}
|
||||||
|
return result + popupBackground.padding * 2 + root.padding * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
root.visible = true;
|
||||||
|
root.menuOpened(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
root.visible = false;
|
||||||
|
while (stackView.depth > 1)
|
||||||
|
stackView.pop();
|
||||||
|
root.menuClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.BackButton | Qt.RightButton
|
||||||
|
onClicked: event => {
|
||||||
|
if ((event.button === Qt.BackButton || event.button === Qt.RightButton) && stackView.depth > 1)
|
||||||
|
stackView.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRectangularShadow {
|
||||||
|
target: popupBackground
|
||||||
|
opacity: popupBackground.opacity
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: popupBackground
|
||||||
|
readonly property real padding: 4
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: Config.options.bar.vertical ? parent.verticalCenter : undefined
|
||||||
|
top: Config.options.bar.vertical ? undefined : Config.options.bar.bottom ? undefined : parent.top
|
||||||
|
bottom: Config.options.bar.vertical ? undefined : Config.options.bar.bottom ? parent.bottom : undefined
|
||||||
|
margins: root.padding
|
||||||
|
}
|
||||||
|
|
||||||
|
color: Appearance.colors.colLayer0
|
||||||
|
radius: Appearance.rounding.windowRounding
|
||||||
|
border.width: 1
|
||||||
|
border.color: Appearance.colors.colLayer0Border
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
opacity: 0
|
||||||
|
Component.onCompleted: opacity = 1
|
||||||
|
implicitWidth: stackView.implicitWidth + popupBackground.padding * 2
|
||||||
|
implicitHeight: stackView.implicitHeight + popupBackground.padding * 2
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
Behavior on implicitHeight {
|
||||||
|
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
StackView {
|
||||||
|
id: stackView
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: popupBackground.padding
|
||||||
|
}
|
||||||
|
pushEnter: NoAnim {}
|
||||||
|
pushExit: NoAnim {}
|
||||||
|
popEnter: NoAnim {}
|
||||||
|
popExit: NoAnim {}
|
||||||
|
|
||||||
|
implicitWidth: currentItem.implicitWidth
|
||||||
|
implicitHeight: currentItem.implicitHeight
|
||||||
|
|
||||||
|
initialItem: SubMenu {
|
||||||
|
handle: root.trayItemMenuHandle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component NoAnim: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component SubMenu: ColumnLayout {
|
||||||
|
id: submenu
|
||||||
|
required property QsMenuHandle handle
|
||||||
|
property bool isSubMenu: false
|
||||||
|
property bool shown: false
|
||||||
|
opacity: shown ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: shown = true
|
||||||
|
StackView.onActivating: shown = true
|
||||||
|
StackView.onDeactivating: shown = false
|
||||||
|
StackView.onRemoved: destroy()
|
||||||
|
|
||||||
|
QsMenuOpener {
|
||||||
|
id: menuOpener
|
||||||
|
menu: submenu.handle
|
||||||
|
}
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: submenu.isSubMenu
|
||||||
|
active: visible
|
||||||
|
sourceComponent: RippleButton {
|
||||||
|
id: backButton
|
||||||
|
buttonRadius: popupBackground.radius - popupBackground.padding
|
||||||
|
horizontalPadding: 12
|
||||||
|
implicitWidth: contentItem.implicitWidth + horizontalPadding * 2
|
||||||
|
implicitHeight: 36
|
||||||
|
|
||||||
|
onClicked: stackView.pop()
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: backButton.horizontalPadding
|
||||||
|
rightMargin: backButton.horizontalPadding
|
||||||
|
}
|
||||||
|
spacing: 8
|
||||||
|
MaterialSymbol {
|
||||||
|
iconSize: 20
|
||||||
|
text: "chevron_left"
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: Translation.tr("Back")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: menuEntriesRepeater
|
||||||
|
property bool iconColumnNeeded: {
|
||||||
|
for (let i = 0; i < menuOpener.children.values.length; i++) {
|
||||||
|
if (menuOpener.children.values[i].icon.length > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
property bool specialInteractionColumnNeeded: {
|
||||||
|
for (let i = 0; i < menuOpener.children.values.length; i++) {
|
||||||
|
if (menuOpener.children.values[i].buttonType !== QsMenuButtonType.None)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
model: menuOpener.children
|
||||||
|
delegate: SysTrayMenuEntry {
|
||||||
|
required property QsMenuEntry modelData
|
||||||
|
forceIconColumn: menuEntriesRepeater.iconColumnNeeded
|
||||||
|
forceSpecialInteractionColumn: menuEntriesRepeater.specialInteractionColumnNeeded
|
||||||
|
menuEntry: modelData
|
||||||
|
|
||||||
|
buttonRadius: popupBackground.radius - popupBackground.padding
|
||||||
|
|
||||||
|
onDismiss: root.close()
|
||||||
|
onOpenSubmenu: handle => {
|
||||||
|
stackView.push(subMenuComponent.createObject(null, {
|
||||||
|
handle: handle,
|
||||||
|
isSubMenu: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: subMenuComponent
|
||||||
|
SubMenu {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.widgets
|
||||||
|
import qs.modules.common.functions
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
|
||||||
|
RippleButton {
|
||||||
|
id: root
|
||||||
|
required property QsMenuEntry menuEntry
|
||||||
|
property bool forceIconColumn: false
|
||||||
|
property bool forceSpecialInteractionColumn: false
|
||||||
|
readonly property bool hasIcon: menuEntry.icon.length > 0
|
||||||
|
readonly property bool hasSpecialInteraction: menuEntry.buttonType !== QsMenuButtonType.None
|
||||||
|
|
||||||
|
signal dismiss()
|
||||||
|
signal openSubmenu(handle: QsMenuHandle)
|
||||||
|
|
||||||
|
colBackground: menuEntry.isSeparator ? Appearance.m3colors.m3outlineVariant : ColorUtils.transparentize(Appearance.colors.colLayer0)
|
||||||
|
enabled: !menuEntry.isSeparator
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
horizontalPadding: 12
|
||||||
|
implicitWidth: contentItem.implicitWidth + horizontalPadding * 2
|
||||||
|
implicitHeight: menuEntry.isSeparator ? 1 : 36
|
||||||
|
Layout.topMargin: menuEntry.isSeparator ? 4 : 0
|
||||||
|
Layout.bottomMargin: menuEntry.isSeparator ? 4 : 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (menuEntry.isSeparator) {
|
||||||
|
root.buttonColor = root.colBackground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseAction: () => {
|
||||||
|
if (menuEntry.hasChildren) {
|
||||||
|
root.openSubmenu(root.menuEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menuEntry.triggered();
|
||||||
|
root.dismiss();
|
||||||
|
}
|
||||||
|
altAction: (event) => { // Not hog right-click
|
||||||
|
event.accepted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
id: contentItem
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: root.horizontalPadding
|
||||||
|
rightMargin: root.horizontalPadding
|
||||||
|
}
|
||||||
|
spacing: 8
|
||||||
|
visible: !root.menuEntry.isSeparator
|
||||||
|
|
||||||
|
// Interaction: checkbox or radio button
|
||||||
|
Item {
|
||||||
|
visible: root.hasSpecialInteraction || root.forceSpecialInteractionColumn
|
||||||
|
implicitWidth: 20
|
||||||
|
implicitHeight: 20
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
anchors.fill: parent
|
||||||
|
active: root.menuEntry.buttonType === QsMenuButtonType.RadioButton
|
||||||
|
|
||||||
|
sourceComponent: StyledRadioButton {
|
||||||
|
padding: 0
|
||||||
|
checked: root.menuEntry.checkState === Qt.Checked
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked) root.clicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
anchors.fill: parent
|
||||||
|
active: root.menuEntry.buttonType === QsMenuButtonType.CheckBox && root.menuEntry.checkState !== Qt.Unchecked
|
||||||
|
|
||||||
|
sourceComponent: MaterialSymbol {
|
||||||
|
text: root.menuEntry.checkState === Qt.PartiallyChecked ? "check_indeterminate_small" : "check"
|
||||||
|
iconSize: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button icon
|
||||||
|
Item {
|
||||||
|
visible: root.hasIcon || root.forceIconColumn
|
||||||
|
implicitWidth: 20
|
||||||
|
implicitHeight: 20
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
active: root.menuEntry.icon.length > 0
|
||||||
|
sourceComponent: IconImage {
|
||||||
|
asynchronous: true
|
||||||
|
source: root.menuEntry.icon
|
||||||
|
implicitSize: 20
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: label
|
||||||
|
text: root.menuEntry.text
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.smallie
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: root.menuEntry.hasChildren
|
||||||
|
|
||||||
|
sourceComponent: MaterialSymbol {
|
||||||
|
text: "chevron_right"
|
||||||
|
iconSize: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -212,6 +212,7 @@ Singleton {
|
|||||||
property QtObject pixelSize: QtObject {
|
property QtObject pixelSize: QtObject {
|
||||||
property int smallest: 10
|
property int smallest: 10
|
||||||
property int smaller: 12
|
property int smaller: 12
|
||||||
|
property int smallie: 13
|
||||||
property int small: 15
|
property int small: 15
|
||||||
property int normal: 16
|
property int normal: 16
|
||||||
property int large: 17
|
property int large: 17
|
||||||
@@ -254,14 +255,8 @@ Singleton {
|
|||||||
easing.bezierCurve: root.animation.elementMove.bezierCurve
|
easing.bezierCurve: root.animation.elementMove.bezierCurve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property Component colorAnimation: Component {
|
|
||||||
ColorAnimation {
|
|
||||||
duration: root.animation.elementMove.duration
|
|
||||||
easing.type: root.animation.elementMove.type
|
|
||||||
easing.bezierCurve: root.animation.elementMove.bezierCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject elementMoveEnter: QtObject {
|
property QtObject elementMoveEnter: QtObject {
|
||||||
property int duration: 400
|
property int duration: 400
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
@@ -275,6 +270,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject elementMoveExit: QtObject {
|
property QtObject elementMoveExit: QtObject {
|
||||||
property int duration: 200
|
property int duration: 200
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
@@ -288,6 +284,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject elementMoveFast: QtObject {
|
property QtObject elementMoveFast: QtObject {
|
||||||
property int duration: animationCurves.expressiveEffectsDuration
|
property int duration: animationCurves.expressiveEffectsDuration
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
@@ -304,6 +301,21 @@ Singleton {
|
|||||||
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
|
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property QtObject elementResize: QtObject {
|
||||||
|
property int duration: 400
|
||||||
|
property int type: Easing.BezierSpline
|
||||||
|
property list<real> bezierCurve: animationCurves.emphasized
|
||||||
|
property int velocity: 650
|
||||||
|
property Component numberAnimation: Component {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: root.animation.elementResize.duration
|
||||||
|
easing.type: root.animation.elementResize.type
|
||||||
|
easing.bezierCurve: root.animation.elementResize.bezierCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property QtObject clickBounce: QtObject {
|
property QtObject clickBounce: QtObject {
|
||||||
property int duration: 200
|
property int duration: 200
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
@@ -315,11 +327,13 @@ Singleton {
|
|||||||
easing.bezierCurve: root.animation.clickBounce.bezierCurve
|
easing.bezierCurve: root.animation.clickBounce.bezierCurve
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject scroll: QtObject {
|
property QtObject scroll: QtObject {
|
||||||
property int duration: 200
|
property int duration: 200
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
property list<real> bezierCurve: animationCurves.standardDecel
|
property list<real> bezierCurve: animationCurves.standardDecel
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject menuDecel: QtObject {
|
property QtObject menuDecel: QtObject {
|
||||||
property int duration: 350
|
property int duration: 350
|
||||||
property int type: Easing.OutExpo
|
property int type: Easing.OutExpo
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Button {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
onPressed: (event) => {
|
onPressed: (event) => {
|
||||||
if(event.button === Qt.RightButton) {
|
if(event.button === Qt.RightButton) {
|
||||||
if (root.altAction) root.altAction();
|
if (root.altAction) root.altAction(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(event.button === Qt.MiddleButton) {
|
if(event.button === Qt.MiddleButton) {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import Quickshell.Services.Pipewire
|
|||||||
|
|
||||||
RadioButton {
|
RadioButton {
|
||||||
id: root
|
id: root
|
||||||
implicitHeight: contentItem.implicitHeight + 4 * 2
|
padding: 4
|
||||||
|
implicitHeight: contentItem.implicitHeight + padding * 2
|
||||||
property string description
|
property string description
|
||||||
property color activeColor: Appearance?.colors.colPrimary ?? "#685496"
|
property color activeColor: Appearance?.colors.colPrimary ?? "#685496"
|
||||||
property color inactiveColor: Appearance?.m3colors.m3onSurfaceVariant ?? "#45464F"
|
property color inactiveColor: Appearance?.m3colors.m3onSurfaceVariant ?? "#45464F"
|
||||||
|
|||||||
Reference in New Issue
Block a user