publish: the public projection begins here
This is a projection, not a development branch. The tree above was constructed from the internal source named below under a manifest that decides which paths may leave, then scanned as a whole tree rather than as a series of patches, and only then published. Public history starts here because the history before it was not admissible, and neither was the tree. What used to stand in this repository included a rescue copy of another machine, a directory of phone handoffs, deployment wired to one house, and a submodule pointing at a forge no stranger can reach. None of that was ever the product. It stays in the private forge, which is allowed to hold the whole working organism, and this is what was deliberately sent out instead. Three mechanisms produced this tree, in decreasing order of trust. A top-level path the manifest does not name never arrives at all, which is the one that catches directories nobody has thought of yet. Named internal files inside admitted roots are dropped. A short, reviewed table replaces deployment defaults that a public build must not carry -- an endpoint aimed at one LAN, a VPN profile belonging to one phone, packaging built from one checkout path. Everything after this commit is an ordinary publication with the same three trailers, so a force push stops being routine and starts meaning that something deliberate happened. The trailers bind the projection to its source without pretending the public SHA is the private one: same lineage, different tree, and the record says so. Source-Sha: 8f27b1e76a8fef560a336aba18e6990713ff1047 Policy-Sha: 6b261d2f3e6e1fb19874846ba4bb1dfe15565d25b8618c1c1afba0419c101d27 Tree-Digest: 18ec3563c5e5ef9a414993a9f6734b251ff9ed3cd56eebdd6cac01e45c6e3067
This commit is contained in:
commit
8f42fc953d
1476 changed files with 238455 additions and 0 deletions
|
|
@ -0,0 +1,42 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
WButton {
|
||||
id: root
|
||||
|
||||
colBackground: Looks.colors.bg1
|
||||
colBackgroundHover: Looks.colors.bg1Hover
|
||||
colBackgroundActive: Looks.colors.bg1Active
|
||||
property color colBackgroundBorder
|
||||
property color color
|
||||
property alias border: background.border
|
||||
property alias shinyColor: background.borderColor
|
||||
|
||||
colBackgroundBorder: ColorUtils.transparentize(color, (root.checked || root.hovered) ? Looks.backgroundTransparency : 0)
|
||||
color: {
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive
|
||||
} else if ((root.hovered && !root.down) || root.checked) {
|
||||
return root.colBackgroundHover
|
||||
} else {
|
||||
return root.colBackground
|
||||
}
|
||||
}
|
||||
|
||||
background: AcrylicRectangle {
|
||||
id: background
|
||||
shiny: ((root.hovered && !root.down) || root.checked)
|
||||
color: root.color
|
||||
radius: Looks.radius.medium
|
||||
border.width: 1
|
||||
border.color: root.colBackgroundBorder
|
||||
|
||||
Behavior on border.color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool shiny: true // Top border
|
||||
property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Hover, 0.7)
|
||||
property color internalBorderColor: ColorUtils.transparentize(borderColor, shiny ? 0.0 : 1)
|
||||
color: Looks.colors.bg1Hover
|
||||
radius: Looks.radius.medium
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
Behavior on internalBorderColor {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
onInternalBorderColorChanged: {
|
||||
borderCanvas.requestPaint();
|
||||
}
|
||||
|
||||
// 1px border at the top or bottom
|
||||
Canvas {
|
||||
id: borderCanvas
|
||||
anchors.fill: parent
|
||||
// For dark mode we have a shiny top border, and for light mode we have sort of a shadow
|
||||
rotation: Looks.dark ? 0 : 180
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
var borderColor = root.internalBorderColor;
|
||||
|
||||
var r = root.radius;
|
||||
var fadeLength = Math.max(1, r);
|
||||
var fadeLengthPercent = fadeLength / width;
|
||||
|
||||
// Compute normalized stops
|
||||
var leftFadeStop = fadeLengthPercent;
|
||||
var rightFadeStop = 1 - fadeLengthPercent;
|
||||
|
||||
var grad = ctx.createLinearGradient(0, 0, width, 0);
|
||||
grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
grad.addColorStop(leftFadeStop, borderColor);
|
||||
grad.addColorStop(rightFadeStop, borderColor);
|
||||
grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
|
||||
ctx.strokeStyle = grad;
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(r, 0.5);
|
||||
ctx.lineTo(width - r, 0.5);
|
||||
// Top-right curve
|
||||
ctx.arcTo(width, 0.5, width, r + 0.5, r);
|
||||
// Top-left curve
|
||||
ctx.moveTo(width - r, 0.5);
|
||||
ctx.arcTo(0, 0.5, 0, r + 0.5, r);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
color: Looks.colors.bgPanelBody
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
import Quickshell
|
||||
|
||||
Button {
|
||||
id: reusableCloseButton
|
||||
implicitHeight: 30
|
||||
implicitWidth: 30
|
||||
property alias radius: closeButtonBg.radius
|
||||
|
||||
Rectangle {
|
||||
z: 0
|
||||
color: "transparent"
|
||||
anchors.fill: closeButtonBg
|
||||
anchors.margins: -1
|
||||
opacity: closeButtonBg.opacity
|
||||
border.width: 1
|
||||
radius: closeButtonBg.radius + 1
|
||||
border.color: Looks.colors.bg2Border
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: closeButtonBg
|
||||
z: 1
|
||||
opacity: reusableCloseButton.hovered ? 1 : 0
|
||||
color: reusableCloseButton.pressed ? Looks.colors.dangerActive : Looks.colors.danger
|
||||
Behavior on opacity {
|
||||
animation: Looks.transition.opacity.createObject(this)
|
||||
}
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: FluentIcon {
|
||||
z: 2
|
||||
anchors.centerIn: parent
|
||||
icon: "dismiss"
|
||||
implicitSize: 10
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import QtQuick
|
||||
import org.kde.kirigami as Kirigami
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Kirigami.Icon {
|
||||
id: root
|
||||
required property string icon
|
||||
property bool filled: false
|
||||
property alias monochrome: root.isMask
|
||||
// Should be 16, but it appears the icons have some padding,
|
||||
// Unlike the Windows-only Segoe UI icons, the open source FluentUI ones are hella small
|
||||
property int implicitSize: 20
|
||||
implicitWidth: implicitSize
|
||||
implicitHeight: implicitSize
|
||||
|
||||
source: icon === "" ? "" : `${Looks.iconsPath}/${root.icon}${filled ? "-filled" : ""}.svg`
|
||||
fallback: root.icon
|
||||
roundToIconSize: false
|
||||
color: Looks.colors.fg
|
||||
isMask: true
|
||||
animated: true
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
|
||||
implicitWidth: 358
|
||||
implicitHeight: 47
|
||||
}
|
||||
266
surfaces/quickshell/ii-base/modules/waffle/looks/Looks.qml
Normal file
266
surfaces/quickshell/ii-base/modules/waffle/looks/Looks.qml
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
property QtObject darkColors
|
||||
property QtObject lightColors
|
||||
property QtObject colors
|
||||
property QtObject radius
|
||||
property QtObject font
|
||||
property QtObject transition
|
||||
property string iconsPath: `${Directories.assetsPath}/icons/fluent`
|
||||
property bool dark: Appearance.m3colors.darkmode
|
||||
|
||||
readonly property bool transparencyEnabled: Config.options.appearance.transparency.enable
|
||||
property real backgroundTransparency: transparencyEnabled ? 0.16 : 0
|
||||
property real panelBackgroundTransparency: transparencyEnabled ? 0.14 : 0
|
||||
property real panelLayerTransparency: root.dark ? 0.9 : 0.7
|
||||
property real contentTransparency: root.dark ? 0.87 : 0.5
|
||||
function applyBackgroundTransparency(col) {
|
||||
return ColorUtils.applyAlpha(col, 1 - root.backgroundTransparency)
|
||||
}
|
||||
function applyContentTransparency(col) {
|
||||
return ColorUtils.applyAlpha(col, 1 - root.contentTransparency)
|
||||
}
|
||||
lightColors: QtObject {
|
||||
id: lightColors
|
||||
property color bgPanelBody: "#F2F2F2"
|
||||
property color bgPanelSeparator: "#E0E0E0"
|
||||
property color bg0: "#EEEEEE"
|
||||
property color bg0Border: '#BEBEBE'
|
||||
property color bg1Base: "#F7F7F7"
|
||||
property color bg1: "#F7F7F7"
|
||||
property color bg1Hover: "#F7F7F7"
|
||||
property color bg1Active: '#EFEFEF'
|
||||
property color bg1Border: '#E9E9E9'
|
||||
property color bg2: "#FBFBFB"
|
||||
property color bg2Base: "#FBFBFB"
|
||||
property color bg2Hover: '#ffffff'
|
||||
property color bg2Active: '#eeeeee'
|
||||
property color bg2Border: '#E0E0E0'
|
||||
property color subfg: "#5C5C5C"
|
||||
property color fg: "#000000"
|
||||
property color fg1: "#626262"
|
||||
property color inactiveIcon: "#C4C4C4"
|
||||
property color controlBgInactive: '#555458'
|
||||
property color controlBg: '#807F85'
|
||||
property color controlBgHover: '#57575B'
|
||||
property color controlFg: "#FFFFFF"
|
||||
property color accentUnfocused: "#848484"
|
||||
property color link: "#235CCF"
|
||||
property color inputBg: ColorUtils.transparentize(bg0, 0.4)
|
||||
}
|
||||
darkColors: QtObject {
|
||||
id: darkColors
|
||||
property color bgPanelBody: '#242424'
|
||||
property color bgPanelSeparator: "#191919"
|
||||
property color bg0: "#1C1C1C"
|
||||
property color bg0Border: "#404040"
|
||||
property color bg1Base: '#2C2C2C'
|
||||
property color bg1: '#2C2C2C'
|
||||
property color bg1Hover: "#292929"
|
||||
property color bg1Active: '#252525'
|
||||
property color bg1Border: '#bebebe'
|
||||
property color bg2Base: "#313131"
|
||||
property color bg2: '#313131'
|
||||
property color bg2Hover: '#363636'
|
||||
property color bg2Active: '#2B2B2B'
|
||||
property color bg2Border: '#404040'
|
||||
property color subfg: "#CED1D7"
|
||||
property color fg: "#FFFFFF"
|
||||
property color fg1: "#D1D1D1"
|
||||
property color inactiveIcon: "#494949"
|
||||
property color controlBgInactive: "#CDCECF"
|
||||
property color controlBg: "#9B9B9B"
|
||||
property color controlBgHover: "#CFCED1"
|
||||
property color controlFg: "#454545"
|
||||
property color accentUnfocused: "#989898"
|
||||
property color link: "#A7C9FC"
|
||||
property color inputBg: ColorUtils.transparentize(darkColors.bg0, 0.5)
|
||||
}
|
||||
colors: QtObject {
|
||||
id: colors
|
||||
// Special
|
||||
property color shadow: ColorUtils.transparentize('#161616', 0.62)
|
||||
property color ambientShadow: ColorUtils.transparentize("#000000", 0.75)
|
||||
property color bgPanelFooterBase: root.dark ? root.darkColors.bg0 : root.lightColors.bg0
|
||||
property color bgPanelFooterBackground: ColorUtils.transparentize(root.dark ? root.darkColors.bg0 : root.lightColors.bg0, root.panelBackgroundTransparency)
|
||||
property color bgPanelFooter: ColorUtils.transparentize(bgPanelFooterBackground, root.panelLayerTransparency)
|
||||
property color bgPanelBodyBase: root.dark ? root.darkColors.bgPanelBody : root.lightColors.bgPanelBody
|
||||
property color bgPanelBody: ColorUtils.solveOverlayColor(bgPanelFooterBackground,bgPanelBodyBase, 1 - root.panelLayerTransparency)
|
||||
property color bgPanelSeparator: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bgPanelSeparator : root.lightColors.bgPanelSeparator, 1 - root.panelBackgroundTransparency)
|
||||
// Layer 0
|
||||
property color bg0Base: root.dark ? root.darkColors.bg0 : root.lightColors.bg0
|
||||
property color bg0: ColorUtils.transparentize(bg0Base, root.backgroundTransparency)
|
||||
property color bg0Border: ColorUtils.transparentize(root.dark ? root.darkColors.bg0Border : root.lightColors.bg0Border, root.backgroundTransparency)
|
||||
// Layer 1
|
||||
property color bg1Base: root.dark ? root.darkColors.bg1 : root.lightColors.bg1
|
||||
property color bg1: ColorUtils.solveOverlayColor(bg0Base, bg1Base, 1 - root.contentTransparency)
|
||||
property color bg1Hover: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Hover : root.lightColors.bg1Hover, 1 - root.contentTransparency)
|
||||
property color bg1Active: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Active : root.lightColors.bg1Active, 1 - root.contentTransparency)
|
||||
property color bg1Border: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Border : root.lightColors.bg1Border, 1 - root.contentTransparency)
|
||||
// Layer 2
|
||||
property color bg2Base: root.dark ? root.darkColors.bg2 : root.lightColors.bg2
|
||||
property color bg2: ColorUtils.solveOverlayColor(bgPanelBodyBase, bg2Base, 1 - root.contentTransparency)
|
||||
property color bg2Hover: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Hover : root.lightColors.bg2Hover, 1 - root.contentTransparency)
|
||||
property color bg2Active: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Active : root.lightColors.bg2Active, 1 - root.contentTransparency)
|
||||
property color bg2Border: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Border : root.lightColors.bg2Border, 1 - root.contentTransparency)
|
||||
// Foreground / Text
|
||||
property color subfg: root.dark ? root.darkColors.subfg : root.lightColors.subfg
|
||||
property color fg: root.dark ? root.darkColors.fg : root.lightColors.fg
|
||||
property color fg1: root.dark ? root.darkColors.fg1 : root.lightColors.fg1
|
||||
property color inactiveIcon: root.dark ? root.darkColors.inactiveIcon : root.lightColors.inactiveIcon
|
||||
property color link: root.dark ? root.darkColors.link : root.lightColors.link
|
||||
// Controls
|
||||
property color controlBgInactive: root.dark ? root.darkColors.controlBgInactive : root.lightColors.controlBgInactive
|
||||
property color controlBg: root.dark ? root.darkColors.controlBg : root.lightColors.controlBg
|
||||
property color controlBgHover: root.dark ? root.darkColors.controlBgHover : root.lightColors.controlBgHover
|
||||
property color controlFg: root.dark ? root.darkColors.controlFg : root.lightColors.controlFg
|
||||
property color inputBg: root.dark ? root.darkColors.inputBg : root.lightColors.inputBg
|
||||
property color danger: "#C42B1C"
|
||||
property color dangerActive: "#B62D1F"
|
||||
property color warning: "#FF9900"
|
||||
// Accent
|
||||
property color accent: Appearance.colors.colPrimary
|
||||
property color accentHover: Appearance.colors.colPrimaryHover
|
||||
property color accentActive: Appearance.colors.colPrimaryActive
|
||||
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
|
||||
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
|
||||
property color selection: Appearance.colors.colPrimaryContainer
|
||||
property color selectionFg: Appearance.colors.colOnPrimaryContainer
|
||||
}
|
||||
|
||||
radius: QtObject {
|
||||
id: radius
|
||||
property int none: 0
|
||||
property int small: 2
|
||||
property int medium: 4
|
||||
property int large: 8
|
||||
property int xLarge: 12
|
||||
}
|
||||
|
||||
font: QtObject {
|
||||
id: font
|
||||
property QtObject family: QtObject {
|
||||
property string ui: "Noto Sans"
|
||||
}
|
||||
property QtObject weight: QtObject { // Noto is not Segoe, so we might use slightly different weights
|
||||
property int thin: Font.Normal
|
||||
property int regular: Font.Medium
|
||||
property int strong: Font.DemiBold
|
||||
property int stronger: (Font.DemiBold + 2*Font.Bold) / 3
|
||||
property int strongest: Font.Bold
|
||||
}
|
||||
property QtObject pixelSize: QtObject {
|
||||
property real normal: 11
|
||||
property real large: 13
|
||||
property real larger: 15
|
||||
property real xlarger: 17
|
||||
}
|
||||
property QtObject variableAxes: QtObject {
|
||||
property var ui: ({
|
||||
"wdth": 25
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
transition: QtObject {
|
||||
id: transition
|
||||
|
||||
property int velocity: 850
|
||||
|
||||
property QtObject easing: QtObject {
|
||||
property QtObject bezierCurve: QtObject {
|
||||
readonly property list<real> easeInOut: [0.42,0.00,0.58,1.00,1,1]
|
||||
readonly property list<real> easeIn: [0,1,1,1,1,1]
|
||||
readonly property list<real> easeOut: [1,0,1,1,1,1]
|
||||
}
|
||||
}
|
||||
|
||||
property Component color: Component {
|
||||
ColorAnimation {
|
||||
duration: 80
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component opacity: Component {
|
||||
NumberAnimation {
|
||||
duration: 120
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component resize: Component { // TODO: better curve needed
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component enter: Component {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component exit: Component {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
}
|
||||
|
||||
property Component move: Component {
|
||||
NumberAnimation {
|
||||
duration: 170
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeInOut
|
||||
}
|
||||
}
|
||||
|
||||
property Component rotate: Component {
|
||||
NumberAnimation {
|
||||
duration: 170
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeInOut
|
||||
}
|
||||
}
|
||||
|
||||
property Component anchor: Component {
|
||||
AnchorAnimation {
|
||||
duration: 160
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component longMovement: Component {
|
||||
NumberAnimation {
|
||||
duration: 1000
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component scroll: Component {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: [0.0, 0.0, 0.25, 1.0, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import Qt.labs.synchronizer
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property bool showArrows: true
|
||||
property int currentIndex: 0
|
||||
property int count: 1
|
||||
signal clicked(int index)
|
||||
signal increasePage()
|
||||
signal decreasePage()
|
||||
|
||||
visible: count > 1
|
||||
spacing: 6
|
||||
|
||||
NavigationArrow {
|
||||
visible: root.showArrows
|
||||
down: false
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.count
|
||||
delegate: MouseArea {
|
||||
id: pageIndicator
|
||||
required property int index
|
||||
hoverEnabled: true
|
||||
onClicked: root.clicked(index);
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
implicitWidth: 6
|
||||
implicitHeight: 6
|
||||
|
||||
Circle {
|
||||
anchors.centerIn: parent
|
||||
diameter: (index === root.currentIndex || pageIndicator.containsMouse) && !pageIndicator.pressed ? 6 : 4
|
||||
color: pageIndicator.containsMouse ? Looks.colors.controlBgHover : Looks.colors.controlBg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavigationArrow {
|
||||
visible: root.showArrows
|
||||
down: true
|
||||
}
|
||||
|
||||
component NavigationArrow: FluentIcon {
|
||||
id: navArrow
|
||||
required property bool down
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
implicitHeight: 12
|
||||
implicitWidth: 12 - (2 * upArea.containsPress)
|
||||
icon: down ? "caret-down" : "caret-up"
|
||||
color: upArea.containsMouse ? Looks.colors.controlBgHover : Looks.colors.controlBg
|
||||
filled: true
|
||||
opacity: ((down && root.currentIndex < root.count - 1) || (!down && root.currentIndex > 0)) ? 1 : 0
|
||||
MouseArea {
|
||||
id: upArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: navArrow.down ? root.increasePage() : root.decreasePage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property var target
|
||||
z: 0
|
||||
|
||||
anchors {
|
||||
fill: target
|
||||
margins: -border.width
|
||||
}
|
||||
|
||||
border.color: Looks.colors.ambientShadow
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: target.radius + border.width
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick
|
||||
import org.kde.kirigami as Kirigami
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
|
||||
Kirigami.Icon {
|
||||
id: root
|
||||
required property string iconName
|
||||
property bool separateLightDark: false
|
||||
property bool tryCustomIcon: true
|
||||
|
||||
property real implicitSize: 26
|
||||
implicitWidth: implicitSize
|
||||
implicitHeight: implicitSize
|
||||
|
||||
animated: true
|
||||
roundToIconSize: false
|
||||
fallback: root.iconName
|
||||
source: tryCustomIcon ? `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg` : fallback
|
||||
|
||||
color: Looks.colors.fg
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal closed
|
||||
|
||||
required property Item contentItem
|
||||
property real visualMargin: 12
|
||||
property int closeAnimDuration: 150
|
||||
property bool revealFromSides: false
|
||||
property bool revealFromLeft: true
|
||||
|
||||
function close() {
|
||||
closeAnim.start();
|
||||
}
|
||||
|
||||
readonly property bool barAtBottom: Config.options.waffles.bar.bottom
|
||||
|
||||
implicitHeight: contentItem.implicitHeight + visualMargin * 2
|
||||
implicitWidth: contentItem.implicitWidth + visualMargin * 2
|
||||
|
||||
focus: true
|
||||
Keys.onPressed: event => { // Esc to close
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
content.close();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: panelContent
|
||||
anchors {
|
||||
left: (root.revealFromSides && !root.revealFromLeft) ? undefined : parent.left
|
||||
right: (root.revealFromSides && root.revealFromLeft) ? undefined : parent.right
|
||||
top: (!root.revealFromSides && root.barAtBottom) ? undefined : parent.top
|
||||
bottom: (!root.revealFromSides && !root.barAtBottom) ? undefined : parent.bottom
|
||||
// Opening anim
|
||||
bottomMargin: (!root.revealFromSides && root.barAtBottom) ? sourceEdgeMargin : root.visualMargin
|
||||
topMargin: (!root.revealFromSides && !root.barAtBottom) ? sourceEdgeMargin : root.visualMargin
|
||||
leftMargin: (root.revealFromSides && root.revealFromLeft) ? sideEdgeMargin : root.visualMargin
|
||||
rightMargin: (root.revealFromSides && !root.revealFromLeft) ? sideEdgeMargin : root.visualMargin
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
openAnim.start();
|
||||
}
|
||||
|
||||
property real sourceEdgeMargin: -(implicitHeight + root.visualMargin)
|
||||
property real sideEdgeMargin: -(implicitWidth + root.visualMargin)
|
||||
OpenAnim {
|
||||
id: openAnim
|
||||
properties: "sourceEdgeMargin, sideEdgeMargin"
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: closeAnim
|
||||
ParallelAnimation {
|
||||
CloseAnim {
|
||||
property: "sourceEdgeMargin"
|
||||
to: -(implicitHeight + root.visualMargin)
|
||||
}
|
||||
CloseAnim {
|
||||
property: "sideEdgeMargin"
|
||||
to: -(implicitWidth + root.visualMargin)
|
||||
}
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.closed();
|
||||
}
|
||||
}
|
||||
}
|
||||
implicitWidth: root.contentItem.implicitWidth
|
||||
implicitHeight: root.contentItem.implicitHeight
|
||||
children: [root.contentItem]
|
||||
}
|
||||
|
||||
component OpenAnim: PropertyAnimation {
|
||||
target: panelContent
|
||||
to: root.visualMargin
|
||||
duration: 200
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
component CloseAnim: PropertyAnimation {
|
||||
target: panelContent
|
||||
duration: root.closeAnimDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
WButton {
|
||||
id: root
|
||||
|
||||
colBackground: Looks.colors.bg2
|
||||
colBackgroundHover: Looks.colors.bg2Hover
|
||||
colBackgroundActive: Looks.colors.bg2Active
|
||||
property color colBorder: Looks.colors.bg2Border
|
||||
property color colBorderToggled: Looks.colors.accent
|
||||
border.color: checked ? colBorderToggled : colBorder
|
||||
border.width: root.pressed ? 2 : 1
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Button {
|
||||
id: root
|
||||
|
||||
implicitHeight: 36
|
||||
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
property color colBackgroundHover: Looks.colors.bg1Hover
|
||||
property color colBackgroundActive: Looks.colors.bg1Active
|
||||
property color color
|
||||
property color colForeground: Looks.colors.fg
|
||||
color: {
|
||||
if (!root.enabled) return colBackground;
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive
|
||||
} else if ((root.hovered && !root.down) || root.checked) {
|
||||
return root.colBackgroundHover
|
||||
} else {
|
||||
return root.colBackground
|
||||
}
|
||||
}
|
||||
property alias radius: background.radius
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
radius: Looks.radius.medium
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
158
surfaces/quickshell/ii-base/modules/waffle/looks/WButton.qml
Normal file
158
surfaces/quickshell/ii-base/modules/waffle/looks/WButton.qml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
// Generic button with background
|
||||
Button {
|
||||
id: root
|
||||
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
property color colBackgroundHover: Looks.colors.bg2Hover
|
||||
property color colBackgroundActive: Looks.colors.bg2Active
|
||||
property color colBackgroundToggled: Looks.colors.accent
|
||||
property color colBackgroundToggledHover: Looks.colors.accentHover
|
||||
property color colBackgroundToggledActive: Looks.colors.accentActive
|
||||
property color colForeground: Looks.colors.fg
|
||||
property color colForegroundToggled: Looks.colors.accentFg
|
||||
property color colForegroundDisabled: ColorUtils.transparentize(Looks.colors.subfg, 0.4)
|
||||
property alias backgroundOpacity: backgroundRect.opacity
|
||||
property color color: {
|
||||
if (!root.enabled) return colBackground;
|
||||
if (root.checked) {
|
||||
if (root.down) {
|
||||
return root.colBackgroundToggledActive;
|
||||
} else if (root.hovered) {
|
||||
return root.colBackgroundToggledHover;
|
||||
} else {
|
||||
return root.colBackgroundToggled;
|
||||
}
|
||||
}
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive;
|
||||
} else if (root.hovered) {
|
||||
return root.colBackgroundHover;
|
||||
} else {
|
||||
return root.colBackground;
|
||||
}
|
||||
}
|
||||
property color fgColor: {
|
||||
if (!root.enabled) return root.colForegroundDisabled
|
||||
if (root.checked) return root.colForegroundToggled
|
||||
if (root.enabled) return root.colForeground
|
||||
return root.colForeground
|
||||
}
|
||||
property alias horizontalAlignment: buttonText.horizontalAlignment
|
||||
font {
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.large
|
||||
weight: Looks.font.weight.regular
|
||||
}
|
||||
|
||||
// Hover stuff
|
||||
signal hoverTimedOut
|
||||
property bool shouldShowTooltip: false
|
||||
ToolTip.delay: 400
|
||||
property Timer hoverTimer: Timer {
|
||||
id: hoverTimer
|
||||
running: root.hovered
|
||||
interval: root.ToolTip.delay
|
||||
onTriggered: {
|
||||
root.hoverTimedOut();
|
||||
}
|
||||
}
|
||||
onHoverTimedOut: {
|
||||
root.shouldShowTooltip = true;
|
||||
}
|
||||
onHoveredChanged: {
|
||||
if (!root.hovered) {
|
||||
root.shouldShowTooltip = false;
|
||||
root.hoverTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
property alias monochromeIcon: buttonIcon.monochrome
|
||||
property alias buttonSpacing: contentLayout.spacing
|
||||
property bool forceShowIcon: false
|
||||
|
||||
property var altAction: () => {}
|
||||
property var middleClickAction: () => {}
|
||||
|
||||
property real inset: 0
|
||||
topInset: inset
|
||||
bottomInset: inset
|
||||
leftInset: inset
|
||||
rightInset: inset
|
||||
property alias radius: backgroundRect.radius
|
||||
property alias topLeftRadius: backgroundRect.topLeftRadius
|
||||
property alias topRightRadius: backgroundRect.topRightRadius
|
||||
property alias bottomLeftRadius: backgroundRect.bottomLeftRadius
|
||||
property alias bottomRightRadius: backgroundRect.bottomRightRadius
|
||||
property alias border: backgroundRect.border
|
||||
horizontalPadding: 10
|
||||
verticalPadding: 6
|
||||
implicitHeight: contentItem.implicitHeight + verticalPadding * 2 + topInset + bottomInset
|
||||
implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 + leftInset + rightInset
|
||||
|
||||
background: Rectangle {
|
||||
id: backgroundRect
|
||||
radius: Looks.radius.medium
|
||||
color: root.color
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: event => {
|
||||
if (event.button === Qt.LeftButton)
|
||||
root.clicked();
|
||||
if (event.button === Qt.RightButton)
|
||||
root.altAction();
|
||||
if (event.button === Qt.MiddleButton)
|
||||
root.middleClickAction();
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: root.inset
|
||||
}
|
||||
implicitWidth: contentLayout.implicitWidth
|
||||
implicitHeight: contentLayout.implicitHeight
|
||||
RowLayout {
|
||||
id: contentLayout
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: root.horizontalPadding
|
||||
rightMargin: root.horizontalPadding
|
||||
}
|
||||
spacing: 12
|
||||
FluentIcon {
|
||||
id: buttonIcon
|
||||
monochrome: true
|
||||
implicitSize: 18
|
||||
Layout.leftMargin: root.iconLeftMargin
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: root.icon.name
|
||||
color: root.fgColor
|
||||
visible: root.icon.name !== ""
|
||||
}
|
||||
WText {
|
||||
id: buttonText
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
text: root.text
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font: root.font
|
||||
color: root.fgColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
WButton {
|
||||
id: root
|
||||
|
||||
property bool animateChoiceHighlight: true
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: contentItem.implicitWidth
|
||||
horizontalPadding: 10
|
||||
verticalPadding: 11
|
||||
buttonSpacing: 8
|
||||
|
||||
color: {
|
||||
if (root.checked) {
|
||||
if (root.down) {
|
||||
return root.colBackgroundHover;
|
||||
} else if (root.hovered && !root.down) {
|
||||
return root.colBackgroundActive;
|
||||
} else {
|
||||
return root.colBackgroundHover;
|
||||
}
|
||||
}
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive;
|
||||
} else if (root.hovered && !root.down) {
|
||||
return root.colBackgroundHover;
|
||||
} else {
|
||||
return root.colBackground;
|
||||
}
|
||||
}
|
||||
fgColor: colForeground
|
||||
|
||||
background: Rectangle {
|
||||
id: backgroundRect
|
||||
radius: Looks.radius.medium
|
||||
color: root.color
|
||||
Behavior on color {
|
||||
enabled: root.animateChoiceHighlight
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
|
||||
WFadeLoader {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
shown: root.checked
|
||||
sourceComponent: Rectangle {
|
||||
implicitWidth: 3
|
||||
implicitHeight: 3
|
||||
radius: width / 2
|
||||
color: Looks.colors.accent
|
||||
property bool forceZeroHeight: true
|
||||
height: forceZeroHeight ? 0 : Math.max(16, root.background.height - 18 * 2)
|
||||
Component.onCompleted: {
|
||||
forceZeroHeight = false;
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
enabled: root.animateChoiceHighlight
|
||||
animation: Looks.transition.opacity.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import QtQuick
|
||||
import qs.modules.common
|
||||
|
||||
// Yes, this is (mostly) a copy of FadeLoader.
|
||||
// The animation of a Behavior cannot be changed... I'd love to be proven wrong.
|
||||
Loader {
|
||||
id: root
|
||||
property bool shown: true
|
||||
property alias fade: opacityBehavior.enabled
|
||||
property alias animation: opacityBehavior.animation
|
||||
opacity: shown ? 1 : 0
|
||||
visible: opacity > 0
|
||||
active: opacity > 0
|
||||
|
||||
Behavior on opacity {
|
||||
id: opacityBehavior
|
||||
animation: Looks.transition.opacity.createObject(null)
|
||||
}
|
||||
}
|
||||
187
surfaces/quickshell/ii-base/modules/waffle/looks/WIcons.qml
Normal file
187
surfaces/quickshell/ii-base/modules/waffle/looks/WIcons.qml
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
pragma Singleton
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.UPower
|
||||
import qs.services
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
function pathForName(iconName) {
|
||||
return Quickshell.shellPath(`assets/icons/fluent/${iconName}.svg`);
|
||||
}
|
||||
|
||||
function wifiIconForStrength(strength) {
|
||||
if (strength > 75)
|
||||
return "wifi-1";
|
||||
if (strength > 50)
|
||||
return "wifi-2";
|
||||
if (strength > 25)
|
||||
return "wifi-3";
|
||||
return "wifi-4";
|
||||
}
|
||||
|
||||
property string internetIcon: {
|
||||
if (Network.ethernet)
|
||||
return "ethernet";
|
||||
if (Network.wifiEnabled) {
|
||||
const strength = Network.networkStrength;
|
||||
return wifiIconForStrength(strength);
|
||||
}
|
||||
if (Network.wifiStatus === "connecting")
|
||||
return "wifi-4";
|
||||
if (Network.wifiStatus === "disconnected")
|
||||
return "wifi-off";
|
||||
if (Network.wifiStatus === "disabled")
|
||||
return "wifi-off";
|
||||
return "wifi-warning";
|
||||
}
|
||||
|
||||
property string batteryIcon: {
|
||||
if (Battery.isCharging)
|
||||
return "battery-charge";
|
||||
if (Battery.isCriticalAndNotCharging)
|
||||
return "battery-warning";
|
||||
if (Battery.percentage >= 0.9)
|
||||
return "battery-full";
|
||||
return `battery-0`;
|
||||
}
|
||||
|
||||
property string batteryLevelIcon: {
|
||||
const discreteLevel = Math.ceil(Battery.percentage * 10);
|
||||
return `battery-${discreteLevel > 9 ? "full" : discreteLevel}`;
|
||||
}
|
||||
|
||||
property string volumeIcon: {
|
||||
const muted = Audio.sink?.audio.muted ?? false;
|
||||
const volume = Audio.sink?.audio.volume ?? 0;
|
||||
if (muted)
|
||||
return "speaker-mute";
|
||||
if (volume == 0)
|
||||
return "speaker-none";
|
||||
if (volume < 0.5)
|
||||
return "speaker-1";
|
||||
return "speaker";
|
||||
}
|
||||
|
||||
property string micIcon: {
|
||||
const muted = Audio.source?.audio.muted ?? false;
|
||||
return muted ? "mic-off" : "mic";
|
||||
}
|
||||
|
||||
property string bluetoothIcon: BluetoothStatus.connected ? "bluetooth-connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth-disabled"
|
||||
|
||||
property string nightLightIcon: Hyprsunset.temperatureActive ? "weather-moon" : "weather-moon-off"
|
||||
|
||||
property string notificationsIcon: Notifications.silent ? "alert-snooze" : "alert"
|
||||
|
||||
property string powerProfileIcon: {
|
||||
switch (PowerProfiles.profile) {
|
||||
case PowerProfile.PowerSaver:
|
||||
return "leaf-two";
|
||||
case PowerProfile.Balanced:
|
||||
return "flash-on";
|
||||
case PowerProfile.Performance:
|
||||
return "fire";
|
||||
}
|
||||
}
|
||||
|
||||
function audioDeviceIcon(node) {
|
||||
if (!node.isSink)
|
||||
return "mic-on";
|
||||
const monitor = /monitor|hdmi/i;
|
||||
const headphones = /headset|headphone|bluez|wireless/i;
|
||||
const speakers = /speaker|output/i;
|
||||
if (monitor.test(node.nickname) || monitor.test(node.description) || monitor.test(node.name)) {
|
||||
return "desktop-speaker";
|
||||
}
|
||||
if (headphones.test(node.nickname) || headphones.test(node.description) || headphones.test(node.name)) {
|
||||
return "headphones";
|
||||
}
|
||||
if (speakers.test(node.nickname) || speakers.test(node.description) || speakers.test(node.name)) {
|
||||
return "speaker";
|
||||
}
|
||||
return "speaker";
|
||||
}
|
||||
|
||||
function audioAppIcon(node) {
|
||||
let icon;
|
||||
icon = AppSearch.guessIcon(node?.properties["application.icon-name"] ?? "");
|
||||
if (AppSearch.iconExists(icon))
|
||||
return icon;
|
||||
icon = AppSearch.guessIcon(node?.properties["node.name"] ?? "");
|
||||
return icon;
|
||||
}
|
||||
|
||||
function bluetoothDeviceIcon(device) {
|
||||
const systemIconName = device?.icon || "";
|
||||
if (systemIconName.includes("headset") || systemIconName.includes("headphones"))
|
||||
return "headphones";
|
||||
if (systemIconName.includes("audio"))
|
||||
return "speaker";
|
||||
if (systemIconName.includes("phone"))
|
||||
return "phone";
|
||||
if (systemIconName.includes("mouse"))
|
||||
return "bluetooth";
|
||||
if (systemIconName.includes("keyboard"))
|
||||
return "keyboard";
|
||||
return "bluetooth";
|
||||
}
|
||||
|
||||
function fluentFromMaterial(icon) {
|
||||
switch (icon) {
|
||||
case "calculate":
|
||||
return "calculator";
|
||||
case "keyboard_return":
|
||||
return "arrow-enter-left";
|
||||
case "open_in_new":
|
||||
return "open";
|
||||
case "settings_suggest":
|
||||
return "wand";
|
||||
case "terminal":
|
||||
return "app-generic";
|
||||
case "travel_explore":
|
||||
return "globe-search";
|
||||
case "keep":
|
||||
return "pin";
|
||||
case "keep_off":
|
||||
return "pin-off";
|
||||
default:
|
||||
return "apps";
|
||||
}
|
||||
}
|
||||
|
||||
function guessIconForName(name) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (lowerName.includes("app") || lowerName.includes("desktop"))
|
||||
return "apps";
|
||||
if (lowerName.includes("news"))
|
||||
return "news";
|
||||
if (lowerName.includes("new") || lowerName.includes("create") || lowerName.includes("add"))
|
||||
return "add";
|
||||
if (lowerName.includes("open"))
|
||||
return "open";
|
||||
if (lowerName.includes("friends") || lowerName.includes("contact") || lowerName.includes("family"))
|
||||
return "people";
|
||||
if (lowerName.includes("community"))
|
||||
return "people-team";
|
||||
if (lowerName.includes("library"))
|
||||
return "library";
|
||||
if (lowerName.includes("setting"))
|
||||
return "settings";
|
||||
if (lowerName.includes("gallery"))
|
||||
return "image-copy";
|
||||
if (lowerName.includes("server"))
|
||||
return "server";
|
||||
if (lowerName.includes("picture") || lowerName.includes("photo") || lowerName.includes("image"))
|
||||
return "image";
|
||||
if (lowerName.includes("store") || lowerName.includes("shop"))
|
||||
return "store-microsoft";
|
||||
if (lowerName.includes("record") || lowerName.includes("capture"))
|
||||
return "record";
|
||||
if (lowerName.includes("screen") || lowerName.includes("display") || lowerName.includes("monitor") || lowerName.includes("desktop"))
|
||||
return "desktop";
|
||||
|
||||
return "apps";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.services.network
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
StyledIndeterminateProgressBar {
|
||||
id: progressBar
|
||||
implicitHeight: 3
|
||||
background: null
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
width: progressBar.width
|
||||
height: progressBar.height
|
||||
radius: progressBar.height / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
|
||||
ScrollBar.vertical: WScrollBar {}
|
||||
|
||||
displaced: Transition {
|
||||
animations: [Looks.transition.enter.createObject(this, {
|
||||
property: "y"
|
||||
})]
|
||||
}
|
||||
|
||||
}
|
||||
104
surfaces/quickshell/ii-base/modules/waffle/looks/WMenu.qml
Normal file
104
surfaces/quickshell/ii-base/modules/waffle/looks/WMenu.qml
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
property bool downDirection: false
|
||||
property bool hasIcons: false // TODO: implement
|
||||
|
||||
property color color: Looks.colors.bg1Base
|
||||
property alias backgroundPane: bgPane
|
||||
|
||||
implicitWidth: background.implicitWidth + margins * 2
|
||||
implicitHeight: background.implicitHeight + margins * 2
|
||||
margins: 10
|
||||
padding: 3
|
||||
property real sourceEdgeMargin: -implicitHeight
|
||||
clip: true
|
||||
|
||||
enter: Transition {
|
||||
NumberAnimation {
|
||||
property: "sourceEdgeMargin"
|
||||
from: -root.implicitHeight
|
||||
to: root.margins
|
||||
duration: 200
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
exit: Transition {
|
||||
NumberAnimation {
|
||||
property: "sourceEdgeMargin"
|
||||
from: root.margins
|
||||
to: -root.implicitHeight
|
||||
duration: 150
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
}
|
||||
|
||||
background: Item {
|
||||
id: bgItem
|
||||
implicitWidth: bgPane.implicitWidth
|
||||
implicitHeight: bgPane.implicitHeight
|
||||
WPane {
|
||||
id: bgPane
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: root.downDirection ? parent.top : undefined
|
||||
bottom: root.downDirection ? undefined : parent.bottom
|
||||
margins: root.margins
|
||||
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
|
||||
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
|
||||
}
|
||||
contentItem: Rectangle {
|
||||
color: root.color
|
||||
implicitWidth: menuListView.implicitWidth + root.padding * 2
|
||||
implicitHeight: root.contentItem.implicitHeight + root.padding * 2
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
menuListView.itemAtIndex(0)?.forceActiveFocus();
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: menuListView.implicitWidth
|
||||
implicitHeight: menuListView.implicitHeight
|
||||
WListView {
|
||||
id: menuListView
|
||||
interactive: contentHeight > height
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: root.downDirection ? parent.top : undefined
|
||||
bottom: root.downDirection ? undefined : parent.bottom
|
||||
margins: root.margins // ????
|
||||
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
|
||||
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
|
||||
}
|
||||
clip: true
|
||||
implicitHeight: contentHeight
|
||||
implicitWidth: Array.from({
|
||||
length: count
|
||||
}, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b)
|
||||
|
||||
model: root.contentModel
|
||||
}
|
||||
}
|
||||
|
||||
delegate: WMenuItem {
|
||||
id: menuItemDelegate
|
||||
}
|
||||
}
|
||||
127
surfaces/quickshell/ii-base/modules/waffle/looks/WMenuItem.qml
Normal file
127
surfaces/quickshell/ii-base/modules/waffle/looks/WMenuItem.qml
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
MenuItem {
|
||||
id: root
|
||||
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
property color colBackgroundHover: Looks.colors.bg2Hover
|
||||
property color colBackgroundActive: Looks.colors.bg2Active
|
||||
property color colBackgroundToggled: Looks.colors.bg2Hover
|
||||
property color colBackgroundToggledHover: Looks.colors.bg2Active
|
||||
property color colBackgroundToggledActive: Looks.colors.bg2Hover
|
||||
property color colForeground: Looks.colors.fg
|
||||
property color colForegroundToggled: Looks.colors.fg
|
||||
property color colForegroundDisabled: ColorUtils.transparentize(Looks.colors.subfg, 0.4)
|
||||
property color color: {
|
||||
if (!root.enabled)
|
||||
return colBackground;
|
||||
if (root.checked) {
|
||||
if (root.down) {
|
||||
return root.colBackgroundToggledActive;
|
||||
} else if (root.hovered) {
|
||||
return root.colBackgroundToggledHover;
|
||||
} else {
|
||||
return root.colBackgroundToggled;
|
||||
}
|
||||
}
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive;
|
||||
} else if (root.hovered) {
|
||||
return root.colBackgroundHover;
|
||||
} else {
|
||||
return root.colBackground;
|
||||
}
|
||||
}
|
||||
property color fgColor: {
|
||||
if (root.checked)
|
||||
return root.colForegroundToggled;
|
||||
if (root.enabled)
|
||||
return root.colForeground;
|
||||
return root.colForegroundDisabled;
|
||||
}
|
||||
|
||||
property real inset: 2
|
||||
topInset: inset
|
||||
bottomInset: inset
|
||||
leftInset: inset
|
||||
rightInset: inset
|
||||
horizontalPadding: 11
|
||||
|
||||
width: ListView.view?.width
|
||||
height: visible ? implicitHeight : 0
|
||||
|
||||
background: Rectangle {
|
||||
id: backgroundRect
|
||||
radius: Looks.radius.medium
|
||||
color: root.color
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: Math.max(28, contentItem.implicitHeight) + topInset + bottomInset
|
||||
implicitWidth: contentItem.implicitWidth + leftInset + rightInset + leftPadding + rightPadding
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: contentLayout.implicitWidth
|
||||
implicitHeight: contentLayout.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
id: contentLayout
|
||||
anchors.fill: parent
|
||||
spacing: 12
|
||||
FluentIcon {
|
||||
id: buttonIcon
|
||||
monochrome: true
|
||||
implicitSize: 20
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: root.fgColor
|
||||
visible: root.icon.name !== ""
|
||||
icon: root.icon.name
|
||||
}
|
||||
WText {
|
||||
id: buttonText
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
text: root.text
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
color: root.fgColor
|
||||
}
|
||||
}
|
||||
|
||||
WFadeLoader {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: -root.leftPadding + width
|
||||
}
|
||||
shown: root.checked
|
||||
sourceComponent: Rectangle {
|
||||
implicitWidth: 3
|
||||
implicitHeight: 3
|
||||
radius: width / 2
|
||||
color: Looks.colors.accent
|
||||
property bool forceZeroHeight: true
|
||||
height: forceZeroHeight ? 0 : Math.max(root.down ? 10 : 16, root.background.height - 18 * 2)
|
||||
Component.onCompleted: {
|
||||
forceZeroHeight = false;
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
animation: Looks.transition.resize.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import QtQuick
|
||||
import qs
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
MouseArea {
|
||||
id: root
|
||||
|
||||
property real radius: Looks.radius.medium
|
||||
hoverEnabled: true
|
||||
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg2)
|
||||
property color colBackgroundHover: Looks.colors.bg2Hover
|
||||
property color colBackgroundActive: Looks.colors.bg2Active
|
||||
property color colBorder: ColorUtils.transparentize(Looks.colors.bg2Border)
|
||||
property color colBorderHover: Looks.colors.bg2Border
|
||||
|
||||
property color color: {
|
||||
if (containsMouse) {
|
||||
return pressed ? colBackgroundActive : colBackgroundHover;
|
||||
} else {
|
||||
return colBackground;
|
||||
}
|
||||
}
|
||||
|
||||
property color borderColor: {
|
||||
if (containsMouse) {
|
||||
return colBorderHover;
|
||||
} else {
|
||||
return colBorder;
|
||||
}
|
||||
}
|
||||
|
||||
property Item background: Rectangle {
|
||||
id: bgRect
|
||||
parent: root
|
||||
anchors.fill: parent
|
||||
color: root.color
|
||||
radius: root.radius
|
||||
|
||||
border.color: root.borderColor
|
||||
border.width: 1
|
||||
}
|
||||
}
|
||||
60
surfaces/quickshell/ii-base/modules/waffle/looks/WPane.qml
Normal file
60
surfaces/quickshell/ii-base/modules/waffle/looks/WPane.qml
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property Item contentItem
|
||||
property real radius: Looks.radius.large
|
||||
property alias color: contentRect.color
|
||||
property alias border: borderRect
|
||||
property alias borderColor: borderRect.border.color
|
||||
property alias borderWidth: borderRect.border.width
|
||||
|
||||
implicitWidth: borderRect.implicitWidth
|
||||
implicitHeight: borderRect.implicitHeight
|
||||
|
||||
WRectangularShadow {
|
||||
target: borderRect
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: borderRect
|
||||
z: 1
|
||||
|
||||
color: "transparent"
|
||||
radius: root.radius
|
||||
border.color: Looks.colors.bg2Border
|
||||
border.width: 1
|
||||
implicitWidth: contentItem.implicitWidth + border.width * 2
|
||||
implicitHeight: contentItem.implicitHeight + border.width * 2
|
||||
anchors.fill: contentRect
|
||||
anchors.margins: -border.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contentRect
|
||||
anchors.centerIn: parent
|
||||
z: 0
|
||||
|
||||
color: Looks.colors.bgPanelFooterBackground
|
||||
implicitWidth: contentItem.implicitWidth
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
id: contentAreaMask
|
||||
width: contentRect.width
|
||||
height: contentRect.height
|
||||
radius: root.radius - borderRect.border.width
|
||||
}
|
||||
}
|
||||
children: [root.contentItem]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
WButton {
|
||||
id: root
|
||||
|
||||
property alias iconName: iconContent.icon
|
||||
property alias iconSize: iconContent.implicitSize
|
||||
property alias monochrome: iconContent.monochrome
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
|
||||
contentItem: Item {
|
||||
FluentIcon {
|
||||
id: iconContent
|
||||
anchors.centerIn: parent
|
||||
implicitSize: 18
|
||||
icon: root.iconName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: true
|
||||
color: Looks.colors.bgPanelSeparator
|
||||
implicitHeight: 1
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
PopupToolTip {
|
||||
id: root
|
||||
|
||||
required property Item realContentItem
|
||||
realContentItem: WText {
|
||||
text: root.text
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
property real visualMargin: 11
|
||||
verticalPadding: 8
|
||||
horizontalPadding: 10
|
||||
verticalMargin: visualMargin
|
||||
horizontalMargin: visualMargin
|
||||
|
||||
contentItem: WToolTipContent {
|
||||
id: tooltipContent
|
||||
realContentItem: root.realContentItem
|
||||
horizontalPadding: root.horizontalPadding
|
||||
verticalPadding: root.verticalPadding
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Widgets
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
ProgressBar {
|
||||
id: root
|
||||
|
||||
Behavior on value {
|
||||
SmoothedAnimation {
|
||||
velocity: Looks.transition.velocity
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: 4
|
||||
background: null
|
||||
|
||||
contentItem: Item {
|
||||
id: background
|
||||
|
||||
Rectangle {
|
||||
id: trackTrough
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
radius: root.implicitHeight / 2
|
||||
color: Looks.colors.controlBg
|
||||
implicitHeight: root.implicitHeight
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: trackHighlight
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
radius: root.implicitHeight / 2
|
||||
color: Looks.colors.accent
|
||||
implicitHeight: root.implicitHeight
|
||||
width: background.width * root.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
StyledRectangularShadow {
|
||||
blur: 10
|
||||
spread: 2
|
||||
offset: Qt.vector2d(0.0, 4)
|
||||
color: Looks.colors.shadow
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Item {
|
||||
default property Item contentItem
|
||||
property Item shadow: WRectangularShadow {
|
||||
target: contentItem
|
||||
}
|
||||
implicitWidth: contentItem.implicitWidth
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
|
||||
children: [shadow, contentItem]
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
|
||||
ScrollBar {
|
||||
id: root
|
||||
|
||||
policy: ScrollBar.AsNeeded
|
||||
active: hovered || pressed
|
||||
property color color: Looks.colors.controlBg
|
||||
|
||||
contentItem: Rectangle {
|
||||
implicitWidth: root.active ? 4 : 2
|
||||
implicitHeight: root.visualSize
|
||||
radius: 9999
|
||||
color: root.color
|
||||
|
||||
opacity: root.policy === ScrollBar.AlwaysOn || (root.active && root.size < 1.0) ? 0.5 : 0
|
||||
Behavior on opacity {
|
||||
animation: Looks.transition.opacity.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
105
surfaces/quickshell/ii-base/modules/waffle/looks/WSlider.qml
Normal file
105
surfaces/quickshell/ii-base/modules/waffle/looks/WSlider.qml
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Widgets
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Slider {
|
||||
id: root
|
||||
|
||||
property real trackWidth: 4
|
||||
property string tooltipContent: `${Math.round(value * 100)}`
|
||||
property bool scrollable: false
|
||||
stepSize: 0.02
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
implicitHeight: handle.implicitHeight
|
||||
|
||||
Behavior on value { // This makes the adjusted value (like volume) shift smoothly
|
||||
SmoothedAnimation {
|
||||
velocity: Looks.transition.velocity
|
||||
}
|
||||
}
|
||||
|
||||
background: MouseArea {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
|
||||
onWheel: (event) => {
|
||||
if (!root.scrollable) {
|
||||
event.accepted = false;
|
||||
return;
|
||||
}
|
||||
if (event.angleDelta.y > 0) {
|
||||
root.value = Math.min(root.value + root.stepSize, 1)
|
||||
root.moved()
|
||||
} else {
|
||||
root.value = Math.max(root.value - root.stepSize, 0)
|
||||
root.moved()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: trackHighlight
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
topLeftRadius: root.trackWidth / 2
|
||||
bottomLeftRadius: root.trackWidth / 2
|
||||
color: Looks.colors.accent
|
||||
implicitHeight: root.trackWidth
|
||||
width: background.width * root.visualPosition
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: trackTrough
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
topRightRadius: root.trackWidth / 2
|
||||
bottomRightRadius: root.trackWidth / 2
|
||||
color: Looks.colors.controlBg
|
||||
implicitHeight: root.trackWidth
|
||||
width: background.width * (1 - root.visualPosition)
|
||||
}
|
||||
}
|
||||
|
||||
handle: Circle {
|
||||
id: handle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: (diameter / 2) + root.visualPosition * (root.width - diameter) - (diameter / 2)
|
||||
diameter: 20
|
||||
color: Looks.colors.controlFg
|
||||
|
||||
MouseArea {
|
||||
id: handleMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
|
||||
Circle {
|
||||
anchors.centerIn: parent
|
||||
diameter: root.pressed ? 10 : handleMouseArea.containsMouse ? 14 : 12
|
||||
color: Looks.colors.accent
|
||||
|
||||
Behavior on diameter {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
WToolTip {
|
||||
id: tooltip
|
||||
extraVisibleCondition: root.pressed
|
||||
text: root.tooltipContent
|
||||
font.pixelSize: Looks.font.pixelSize.larger
|
||||
verticalPadding: 3
|
||||
horizontalPadding: 8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
StackView {
|
||||
id: root
|
||||
property real moveDistance: 30
|
||||
property int pushDuration: 200
|
||||
property int fadeDuration: 80
|
||||
property list<real> bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||
property list<real> fadeBezierCurve: Looks.transition.easing.bezierCurve.easeInOut
|
||||
clip: true
|
||||
|
||||
background: null
|
||||
|
||||
pushEnter: Transition {
|
||||
XAnimator {
|
||||
from: -root.moveDistance
|
||||
to: 0
|
||||
duration: root.pushDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.bezierCurve
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: root.fadeDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.fadeBezierCurve
|
||||
}
|
||||
}
|
||||
pushExit: Transition {
|
||||
XAnimator {
|
||||
from: 0
|
||||
to: root.moveDistance
|
||||
duration: root.pushDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.bezierCurve
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
from: 1
|
||||
to: 0
|
||||
duration: root.fadeDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.fadeBezierCurve
|
||||
}
|
||||
}
|
||||
popEnter: Transition {
|
||||
XAnimator {
|
||||
from: root.moveDistance
|
||||
to: 0
|
||||
duration: root.pushDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.bezierCurve
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: root.fadeDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.fadeBezierCurve
|
||||
}
|
||||
}
|
||||
popExit: Transition {
|
||||
XAnimator {
|
||||
from: 0
|
||||
to: -root.moveDistance
|
||||
duration: root.pushDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.bezierCurve
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
from: 1
|
||||
to: 0
|
||||
duration: root.fadeDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.fadeBezierCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
66
surfaces/quickshell/ii-base/modules/waffle/looks/WSwitch.qml
Normal file
66
surfaces/quickshell/ii-base/modules/waffle/looks/WSwitch.qml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Switch {
|
||||
id: root
|
||||
|
||||
implicitWidth: 40
|
||||
implicitHeight: 20
|
||||
property real indicatorHeight: 12
|
||||
property real indicatorPressedHeight: 14
|
||||
property real indicatorPressedWidth: 17
|
||||
property color checkedColor: Looks.colors.accent
|
||||
property color uncheckedColor: Looks.colors.bg1
|
||||
property color borderColor: Looks.colors.controlBgInactive
|
||||
|
||||
readonly property real indicatorPressedWidthDiff: indicatorPressedWidth - indicatorHeight
|
||||
|
||||
background: Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
radius: height / 2
|
||||
color: root.checked ? root.checkedColor : root.uncheckedColor
|
||||
border.width: 1
|
||||
border.color: root.checked ? root.checkedColor : root.borderColor
|
||||
|
||||
Behavior on color {
|
||||
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||
}
|
||||
Behavior on border.color {
|
||||
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
// Custom thumb styling
|
||||
indicator: Rectangle {
|
||||
implicitWidth: (root.pressed || root.down) ? root.indicatorPressedWidth : root.indicatorHeight
|
||||
implicitHeight: (root.pressed || root.down) ? root.indicatorPressedHeight : root.indicatorHeight
|
||||
radius: height / 2
|
||||
color: root.checked ? Looks.colors.accentFg : root.borderColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: {
|
||||
if (root.checked) {
|
||||
return 24 - (root.pressed || root.down ? root.indicatorPressedWidthDiff : 0);
|
||||
} else {
|
||||
return (root.pressed || root.down) ? 3 : (Config.options.waffles.tweaks.switchHandlePositionFix ? 4 : 3);
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on anchors.leftMargin {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
Behavior on implicitWidth {
|
||||
animation: Looks.transition.resize.createObject(this)
|
||||
}
|
||||
Behavior on implicitHeight {
|
||||
animation: Looks.transition.resize.createObject(this)
|
||||
}
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
surfaces/quickshell/ii-base/modules/waffle/looks/WText.qml
Normal file
19
surfaces/quickshell/ii-base/modules/waffle/looks/WText.qml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import QtQuick
|
||||
|
||||
Text {
|
||||
id: root
|
||||
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Looks.colors.fg
|
||||
|
||||
font {
|
||||
hintingPreference: Font.PreferDefaultHinting
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.normal
|
||||
weight: Looks.font.weight.regular
|
||||
variableAxes: Looks.font.variableAxes.ui
|
||||
}
|
||||
|
||||
linkColor: Looks.colors.link
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
WButton {
|
||||
id: root
|
||||
implicitHeight: 40
|
||||
implicitWidth: contentItem.implicitWidth + 30
|
||||
color: "transparent"
|
||||
|
||||
contentItem: Item {
|
||||
id: contentItem
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: buttonText.implicitWidth
|
||||
|
||||
WText {
|
||||
id: buttonText
|
||||
anchors.centerIn: parent
|
||||
color: root.pressed ? Looks.colors.fg : Looks.colors.fg1
|
||||
text: root.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import qs.modules.common
|
||||
import QtQuick
|
||||
import QtQuick.Controls.FluentWinUI3
|
||||
import QtQuick.Controls
|
||||
|
||||
TextField {
|
||||
id: root
|
||||
|
||||
clip: true
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Looks.colors.fg
|
||||
|
||||
palette {
|
||||
active: Looks.colors.accent
|
||||
}
|
||||
|
||||
font {
|
||||
hintingPreference: Font.PreferDefaultHinting
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.normal
|
||||
weight: Looks.font.weight.regular
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.IBeamCursor
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
TextInput {
|
||||
id: root
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Looks.colors.fg
|
||||
|
||||
font {
|
||||
hintingPreference: Font.PreferFullHinting
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.large
|
||||
weight: Looks.font.weight.regular
|
||||
}
|
||||
|
||||
selectionColor: Looks.colors.selection
|
||||
selectedTextColor: Looks.colors.selectionFg
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string longestText
|
||||
property alias text: textItem.text
|
||||
property alias font: textItem.font
|
||||
property alias horizontalAlignment: textItem.horizontalAlignment
|
||||
property alias verticalAlignment: textItem.verticalAlignment
|
||||
property alias color: textItem.color
|
||||
|
||||
implicitWidth: longestTextMetrics.width
|
||||
implicitHeight: longestTextMetrics.height
|
||||
|
||||
TextMetrics {
|
||||
id: longestTextMetrics
|
||||
text: root.longestText
|
||||
font {
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.large
|
||||
weight: Looks.font.weight.regular
|
||||
}
|
||||
}
|
||||
|
||||
WText {
|
||||
id: textItem
|
||||
anchors.fill: parent
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
StyledToolTip {
|
||||
id: root
|
||||
|
||||
required property Item realContentItem
|
||||
font {
|
||||
family: Looks.font.family.ui
|
||||
pixelSize: Looks.font.pixelSize.normal
|
||||
weight: Looks.font.weight.regular
|
||||
}
|
||||
realContentItem: WText {
|
||||
text: root.text
|
||||
font: root.font
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
verticalPadding: 8
|
||||
horizontalPadding: 10
|
||||
|
||||
delay: 400
|
||||
|
||||
contentItem: WToolTipContent {
|
||||
id: tooltipContent
|
||||
realContentItem: root.realContentItem
|
||||
horizontalPadding: root.horizontalPadding
|
||||
verticalPadding: root.verticalPadding
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.centerIn: parent
|
||||
required property Item realContentItem
|
||||
property alias radius: realContent.radius
|
||||
property real verticalPadding: 8
|
||||
property real horizontalPadding: 10
|
||||
implicitWidth: realContent.implicitWidth + 2 * 2
|
||||
implicitHeight: realContent.implicitHeight + 2 * 2
|
||||
|
||||
WAmbientShadow {
|
||||
target: realContent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: realContent
|
||||
z: 1
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: root.realContentItem.implicitWidth + root.horizontalPadding * 2
|
||||
implicitHeight: root.realContentItem.implicitHeight + root.verticalPadding * 2
|
||||
color: Looks.colors.bg1Base
|
||||
radius: Looks.radius.medium
|
||||
|
||||
children: [root.realContentItem]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real padding: 9
|
||||
property alias colBackground: background.color
|
||||
property alias spacing: toolbarLayout.spacing
|
||||
property alias radius: background.radius
|
||||
default property alias toolbarData: toolbarLayout.data
|
||||
|
||||
implicitWidth: background.implicitWidth
|
||||
implicitHeight: background.implicitHeight
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
implicitHeight: 50
|
||||
implicitWidth: toolbarLayout.implicitWidth + root.padding * 2
|
||||
radius: Looks.radius.large
|
||||
color: Looks.colors.bg0Base
|
||||
|
||||
border.width: 1
|
||||
border.color: Looks.colors.bg1Border
|
||||
|
||||
RowLayout {
|
||||
id: toolbarLayout
|
||||
spacing: 4
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: root.padding
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
|
||||
WButton {
|
||||
implicitHeight: 32
|
||||
radius: Looks.radius.medium
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
|
||||
WToolbarButton {
|
||||
id: root
|
||||
implicitWidth: height
|
||||
contentItem: Item {
|
||||
FluentIcon {
|
||||
anchors.centerIn: parent
|
||||
icon: root.icon.name
|
||||
implicitSize: 18
|
||||
color: root.fgColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.modules.common
|
||||
|
||||
TabButton {
|
||||
id: root
|
||||
|
||||
implicitWidth: 38
|
||||
implicitHeight: 32
|
||||
padding: 0
|
||||
|
||||
background: null
|
||||
contentItem: Item {
|
||||
FluentIcon {
|
||||
anchors.centerIn: parent
|
||||
icon: root.icon.name
|
||||
color: root.icon.color
|
||||
implicitSize: 18
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
|
||||
Rectangle {
|
||||
Layout.leftMargin: 4
|
||||
Layout.rightMargin: 4
|
||||
implicitHeight: 24
|
||||
implicitWidth: 1
|
||||
color: Looks.colors.bg0Border
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
|
||||
TabBar {
|
||||
id: root
|
||||
implicitHeight: 32
|
||||
|
||||
background: Rectangle {
|
||||
radius: Looks.radius.medium
|
||||
color: Looks.colors.bgPanelFooter
|
||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, 0.7)
|
||||
border.width: 1
|
||||
|
||||
// Indicator
|
||||
Rectangle {
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
leftMargin: root.currentIndex * (root.width / root.count)
|
||||
Behavior on leftMargin {
|
||||
animation: Looks.transition.resize.createObject(this)
|
||||
}
|
||||
}
|
||||
radius: Looks.radius.medium
|
||||
color: Looks.colors.bg2Base
|
||||
border.color: Looks.colors.bg0Border
|
||||
border.width: 1
|
||||
width: root.width / root.count
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 1
|
||||
}
|
||||
implicitWidth: pressDetector.containsPress ? 16 : 12
|
||||
implicitHeight: 3
|
||||
radius: height / 2
|
||||
color: Looks.colors.accent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: pressDetector
|
||||
z: 9999
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
StyledImage {
|
||||
id: avatar
|
||||
Layout.alignment: Qt.AlignTop
|
||||
sourceSize: Qt.size(32, 32)
|
||||
source: Directories.userAvatarPathAccountsService
|
||||
fallbacks: [Directories.userAvatarPathRicersAndWeirdSystems, Directories.userAvatarPathRicersAndWeirdSystems2]
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Circle {
|
||||
diameter: avatar.height
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue