Cleaned up ColorSchemeTab, added program checks, added firefox template
Matugen: added firefox (pywalfox) template SidePanelToggle: use ProgramCheckerService for gpu-screen-recorder ColorSchemeTab: use NCollapsible for matugen templates, use ProgramCheckerService to detect available programs (for matugen templates) NCollapsible: create collapsible category
This commit is contained in:
parent
c0d6780c3d
commit
fa838ecdb1
8 changed files with 514 additions and 148 deletions
193
Widgets/NCollapsible.qml
Normal file
193
Widgets/NCollapsible.qml
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
property string label: ""
|
||||
property string description: ""
|
||||
property bool expanded: false
|
||||
property bool defaultExpanded: false
|
||||
property real contentSpacing: Style.marginM * scaling
|
||||
signal toggled(bool expanded)
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
// Default property to accept children
|
||||
default property alias content: contentLayout.children
|
||||
|
||||
// Header with clickable area
|
||||
Rectangle {
|
||||
id: headerContainer
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: headerContent.implicitHeight + (Style.marginL * scaling * 2)
|
||||
|
||||
// Material 3 style background
|
||||
color: root.expanded ? Color.mSecondary : Color.mSurfaceVariant
|
||||
radius: Style.radiusL * scaling
|
||||
|
||||
// Subtle border
|
||||
border.color: root.expanded ? Color.mOnSecondary : Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
|
||||
// Smooth color transitions
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: headerArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
root.expanded = !root.expanded
|
||||
root.toggled(root.expanded)
|
||||
}
|
||||
|
||||
// Hover effect overlay
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: headerArea.containsMouse ? Color.mOnSurface : Color.transparent
|
||||
opacity: headerArea.containsMouse ? 0.08 : 0
|
||||
radius: headerContainer.radius // Reference the container's radius directly
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: headerContent
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL * scaling
|
||||
spacing: Style.marginM * scaling
|
||||
|
||||
// Expand/collapse icon with rotation animation
|
||||
NIcon {
|
||||
id: chevronIcon
|
||||
icon: "chevron-right"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: root.expanded ? Color.mOnSecondary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
rotation: root.expanded ? 90 : 0
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Header text content - properly contained
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: root.label
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightSemiBold
|
||||
color: root.expanded ? Color.mOnSecondary : Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: root.description
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightRegular
|
||||
color: root.expanded ? Color.mOnSecondary : Color.mOnSurfaceVariant
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
opacity: 0.87
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collapsible content with Material 3 styling
|
||||
Rectangle {
|
||||
id: contentContainer
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginS * scaling
|
||||
|
||||
visible: root.expanded
|
||||
color: Color.mSurface
|
||||
radius: Style.radiusL * scaling
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
|
||||
// Dynamic height based on content
|
||||
Layout.preferredHeight: visible ? contentLayout.implicitHeight + (Style.marginL * scaling * 2) : 0
|
||||
|
||||
// Smooth height animation
|
||||
Behavior on Layout.preferredHeight {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Content layout
|
||||
ColumnLayout {
|
||||
id: contentLayout
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL * scaling
|
||||
spacing: root.contentSpacing
|
||||
|
||||
// Clip content during animation
|
||||
clip: true
|
||||
}
|
||||
|
||||
// Fade in animation for content
|
||||
opacity: root.expanded ? 1.0 : 0.0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize expanded state
|
||||
Component.onCompleted: {
|
||||
root.expanded = root.defaultExpanded
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue