Wallpaper: added fill color that may show up around wallpaper (depends on fillMode)

+ New Widget NColorPicker
+ New Widget NButton
This commit is contained in:
LemmyCook 2025-09-01 22:27:49 -04:00
parent 69a5f0c2c0
commit d5e83aa9de
7 changed files with 411 additions and 5 deletions

200
Widgets/NButton.qml Normal file
View file

@ -0,0 +1,200 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
Rectangle {
id: root
// Public properties
property string text: ""
property string icon: ""
property color backgroundColor: Color.mPrimary
property color textColor: Color.mOnPrimary
property color hoverColor: Color.mTertiary
property color pressColor: Color.mSecondary
property bool enabled: true
property int fontSize: Style.fontSizeM * scaling
property int iconSize: Style.fontSizeL * scaling
property bool outlined: false
property real customWidth: -1
property real customHeight: -1
// Signals
signal clicked
// Internal properties
property bool hovered: false
property bool pressed: false
// Dimensions
implicitWidth: customWidth > 0 ? customWidth : contentRow.implicitWidth + (Style.marginL * 2 * scaling)
implicitHeight: customHeight > 0 ? customHeight : Math.max(Style.baseWidgetSize * scaling,
contentRow.implicitHeight + (Style.marginM * scaling))
// Appearance
radius: Style.radiusS * scaling
color: {
if (!enabled)
return outlined ? Color.transparent : Qt.lighter(Color.mSurfaceVariant, 1.2)
if (pressed)
return pressColor
if (hovered)
return hoverColor
return outlined ? Color.transparent : backgroundColor
}
border.width: outlined ? Math.max(1, Style.borderS * scaling) : 0
border.color: {
if (!enabled)
return Color.mOutline
if (pressed || hovered)
return backgroundColor
return outlined ? backgroundColor : Color.transparent
}
opacity: enabled ? 1.0 : 0.6
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
Behavior on border.color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
// Content
RowLayout {
id: contentRow
anchors.centerIn: parent
spacing: Style.marginS * scaling
// Icon (optional)
NIcon {
visible: root.icon !== ""
text: root.icon
font.pointSize: root.iconSize
color: {
if (!root.enabled)
return Color.mOnSurfaceVariant
if (root.outlined) {
if (root.pressed || root.hovered)
return root.backgroundColor
return root.backgroundColor
}
return root.textColor
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
}
// Text
NText {
visible: root.text !== ""
text: root.text
font.pointSize: root.fontSize
font.weight: Style.fontWeightBold
color: {
if (!root.enabled)
return Color.mOnSurfaceVariant
if (root.outlined) {
if (root.pressed || root.hovered)
return root.textColor
return root.backgroundColor
}
return root.textColor
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
}
}
// Ripple effect
Rectangle {
id: ripple
anchors.centerIn: parent
width: 0
height: width
radius: width / 2
color: root.outlined ? root.backgroundColor : root.textColor
opacity: 0
ParallelAnimation {
id: rippleAnimation
NumberAnimation {
target: ripple
property: "width"
from: 0
to: Math.max(root.width, root.height) * 2
duration: Style.animationFast
easing.type: Easing.OutCubic
}
SequentialAnimation {
NumberAnimation {
target: ripple
property: "opacity"
from: 0
to: 0.2
duration: 100
easing.type: Easing.OutCubic
}
NumberAnimation {
target: ripple
property: "opacity"
from: 0.2
to: 0
duration: 300
easing.type: Easing.InCubic
}
}
}
}
// Mouse interaction
MouseArea {
id: mouseArea
anchors.fill: parent
enabled: root.enabled
hoverEnabled: true
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onEntered: root.hovered = true
onExited: {
root.hovered = false
root.pressed = false
}
onPressed: {
root.pressed = true
rippleAnimation.restart()
}
onReleased: {
if (containsMouse) {
root.clicked()
}
root.pressed = false
}
onCanceled: {
root.pressed = false
root.hovered = false
}
}
}

186
Widgets/NColorPicker.qml Normal file
View file

@ -0,0 +1,186 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Widgets
Rectangle {
id: root
property color selectedColor: "#000000"
property bool expanded: false
signal colorSelected(color color)
signal colorCancelled
implicitWidth: expanded ? 320 * scaling : 150 * scaling
implicitHeight: expanded ? 300 * scaling : 40 * scaling
radius: Style.radiusM * scaling
color: Color.mSurface
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
Behavior on implicitWidth {
NumberAnimation {
duration: Style.animationFast
}
}
Behavior on implicitHeight {
NumberAnimation {
duration: Style.animationFast
}
}
// Collapsed view - just show current color
MouseArea {
visible: !root.expanded
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: root.expanded = true
RowLayout {
anchors.fill: parent
anchors.margins: Style.marginS * scaling
spacing: Style.marginS * scaling
Rectangle {
Layout.preferredWidth: 24 * scaling
Layout.preferredHeight: 24 * scaling
radius: Layout.preferredWidth * 0.5
color: root.selectedColor
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
}
NText {
text: root.selectedColor.toString().toUpperCase()
font.family: Settings.data.ui.fontFixed
Layout.fillWidth: true
}
NIcon {
text: "palette"
color: Color.mOnSurfaceVariant
}
}
}
// Expanded view - color selection
ColumnLayout {
visible: root.expanded
anchors.fill: parent
anchors.margins: Style.marginM * scaling
spacing: Style.marginS * scaling
// Header
RowLayout {
Layout.fillWidth: true
NText {
text: "Select Color"
font.weight: Style.fontWeightBold
Layout.fillWidth: true
}
NIconButton {
icon: "close"
onClicked: root.expanded = false
}
}
// Preset colors grid
Grid {
columns: 9
spacing: Style.marginXS * scaling
Layout.fillWidth: true
property var presetColors: ["#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E", "#607D8B", "#000000", "#FFFFFF", "#F5F5F5", "#E0E0E0", "#9E9E9E"]
Repeater {
model: parent.presetColors
Rectangle {
width: Math.round(29 * scaling)
height: width
radius: Style.radiusXS * scaling
color: modelData
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
border.width: root.selectedColor === modelData ? 2 : 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedColor = modelData
// root.colorSelected(modelData)
}
}
}
}
}
// Custom color input
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS * scaling
NTextInput {
id: hexInput
label: "Hex Color"
text: root.selectedColor.toString().toUpperCase()
fontFamily: Settings.data.ui.fontFixed
Layout.minimumWidth: 100 * scaling
onEditingFinished: {
if (/^#[0-9A-F]{6}$/i.test(text)) {
root.selectedColor = text
root.colorSelected(text)
}
}
}
Rectangle {
Layout.preferredWidth: 32 * scaling
Layout.preferredHeight: 32 * scaling
radius: Layout.preferredWidth * 0.5
color: root.selectedColor
border.color: Color.mOutline
border.width: 1
Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: 5 * scaling
}
}
// Action buttons row
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS * scaling
Item {
Layout.fillWidth: true
} // Spacer
NButton {
text: "Cancel"
outlined: true
customHeight: Style.baseWidgetSize * scaling
fontSize: Style.fontSizeS * scaling
onClicked: {
root.colorCancelled()
root.expanded = false
}
}
NButton {
text: "Apply"
customHeight: Style.baseWidgetSize * scaling
fontSize: Style.fontSizeS * scaling
onClicked: {
root.colorSelected(root.selectedColor)
root.expanded = false
}
}
}
}
}

View file

@ -14,6 +14,7 @@ ColumnLayout {
property int inputMaxWidth: 420 * scaling
property color labelColor: Color.mOnSurface
property color descriptionColor: Color.mOnSurfaceVariant
property string fontFamily: Settings.data.ui.fontDefault
property alias text: input.text
property alias placeholderText: input.placeholderText
@ -74,6 +75,7 @@ ColumnLayout {
color: Color.mOnSurface
placeholderTextColor: Color.mOnSurfaceVariant
background: null
font.family: fontFamily
font.pointSize: Style.fontSizeS * scaling
onEditingFinished: root.editingFinished()
}