refactor: SplitPaneLayout now component
This commit is contained in:
parent
50e29f8be3
commit
ad4213d45c
6 changed files with 1317 additions and 1436 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,7 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
|
import "../components"
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
import qs.components.effects
|
import qs.components.effects
|
||||||
|
|
@ -11,52 +12,17 @@ import Quickshell.Widgets
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
RowLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Session session
|
required property Session session
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: 0
|
SplitPaneLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
Item {
|
leftContent: Component {
|
||||||
id: leftAudioItem
|
|
||||||
Layout.preferredWidth: Math.floor(parent.width * 0.4)
|
|
||||||
Layout.minimumWidth: 420
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: leftAudioClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: leftAudioBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: leftAudioLoader
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
|
||||||
anchors.leftMargin: Appearance.padding.large
|
|
||||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
sourceComponent: audioLeftContentComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerBorder {
|
|
||||||
id: leftAudioBorder
|
|
||||||
leftThickness: 0
|
|
||||||
rightThickness: Appearance.padding.normal / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: audioLeftContentComponent
|
|
||||||
|
|
||||||
StyledFlickable {
|
StyledFlickable {
|
||||||
id: leftAudioFlickable
|
id: leftAudioFlickable
|
||||||
|
|
@ -246,349 +212,321 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
|
||||||
id: rightAudioItem
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: rightAudioClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: rightAudioBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: rightAudioLoader
|
|
||||||
|
|
||||||
|
rightContent: Component {
|
||||||
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.topMargin: Appearance.padding.large * 2
|
anchors.topMargin: Appearance.padding.large * 2
|
||||||
anchors.bottomMargin: Appearance.padding.large * 2
|
anchors.bottomMargin: Appearance.padding.large * 2
|
||||||
anchors.leftMargin: 0
|
anchors.leftMargin: 0
|
||||||
anchors.rightMargin: 0
|
anchors.rightMargin: 0
|
||||||
|
|
||||||
asynchronous: true
|
StyledFlickable {
|
||||||
sourceComponent: audioRightContentComponent
|
id: rightAudioFlickable
|
||||||
}
|
anchors.fill: parent
|
||||||
}
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: contentLayout.height
|
||||||
|
|
||||||
InnerBorder {
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
id: rightAudioBorder
|
flickable: rightAudioFlickable
|
||||||
leftThickness: Appearance.padding.normal / 2
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: audioRightContentComponent
|
|
||||||
|
|
||||||
StyledFlickable {
|
|
||||||
id: rightAudioFlickable
|
|
||||||
flickableDirection: Flickable.VerticalFlick
|
|
||||||
contentHeight: contentLayout.height
|
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
|
||||||
flickable: rightAudioFlickable
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: contentLayout
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: Appearance.padding.large * 2
|
|
||||||
anchors.rightMargin: Appearance.padding.large * 2
|
|
||||||
spacing: Appearance.spacing.normal
|
|
||||||
|
|
||||||
ConnectionHeader {
|
|
||||||
icon: "volume_up"
|
|
||||||
title: qsTr("Audio Settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionHeader {
|
|
||||||
title: qsTr("Output volume")
|
|
||||||
description: qsTr("Control the volume of your output device")
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionContainer {
|
|
||||||
contentSpacing: Appearance.spacing.normal
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
id: contentLayout
|
||||||
spacing: Appearance.spacing.small
|
|
||||||
|
|
||||||
RowLayout {
|
anchors.left: parent.left
|
||||||
Layout.fillWidth: true
|
anchors.right: parent.right
|
||||||
spacing: Appearance.spacing.normal
|
anchors.leftMargin: Appearance.padding.large * 2
|
||||||
|
anchors.rightMargin: Appearance.padding.large * 2
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
StyledText {
|
ConnectionHeader {
|
||||||
text: qsTr("Volume")
|
icon: "volume_up"
|
||||||
font.pointSize: Appearance.font.size.normal
|
title: qsTr("Audio Settings")
|
||||||
font.weight: 500
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
SectionHeader {
|
||||||
|
title: qsTr("Output volume")
|
||||||
|
description: qsTr("Control the volume of your output device")
|
||||||
|
}
|
||||||
|
|
||||||
|
SectionContainer {
|
||||||
|
contentSpacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
StyledRect {
|
RowLayout {
|
||||||
Layout.preferredWidth: 70
|
Layout.fillWidth: true
|
||||||
implicitHeight: outputVolumeInput.implicitHeight + Appearance.padding.small * 2
|
spacing: Appearance.spacing.normal
|
||||||
color: outputVolumeInputHover.containsMouse || outputVolumeInput.activeFocus
|
|
||||||
? Colours.layer(Colours.palette.m3surfaceContainer, 3)
|
|
||||||
: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
border.width: 1
|
|
||||||
border.color: outputVolumeInput.activeFocus
|
|
||||||
? Colours.palette.m3primary
|
|
||||||
: Qt.alpha(Colours.palette.m3outline, 0.3)
|
|
||||||
enabled: !Audio.muted
|
|
||||||
opacity: enabled ? 1 : 0.5
|
|
||||||
|
|
||||||
Behavior on color { CAnim {} }
|
StyledText {
|
||||||
Behavior on border.color { CAnim {} }
|
text: qsTr("Volume")
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
Item {
|
||||||
id: outputVolumeInputHover
|
Layout.fillWidth: true
|
||||||
anchors.fill: parent
|
}
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.IBeamCursor
|
StyledRect {
|
||||||
acceptedButtons: Qt.NoButton
|
Layout.preferredWidth: 70
|
||||||
|
implicitHeight: outputVolumeInput.implicitHeight + Appearance.padding.small * 2
|
||||||
|
color: outputVolumeInputHover.containsMouse || outputVolumeInput.activeFocus
|
||||||
|
? Colours.layer(Colours.palette.m3surfaceContainer, 3)
|
||||||
|
: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
border.width: 1
|
||||||
|
border.color: outputVolumeInput.activeFocus
|
||||||
|
? Colours.palette.m3primary
|
||||||
|
: Qt.alpha(Colours.palette.m3outline, 0.3)
|
||||||
|
enabled: !Audio.muted
|
||||||
|
opacity: enabled ? 1 : 0.5
|
||||||
|
|
||||||
|
Behavior on color { CAnim {} }
|
||||||
|
Behavior on border.color { CAnim {} }
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: outputVolumeInputHover
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.IBeamCursor
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledTextField {
|
||||||
|
id: outputVolumeInput
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Appearance.padding.normal
|
||||||
|
horizontalAlignment: TextInput.AlignHCenter
|
||||||
|
validator: IntValidator { bottom: 0; top: 100 }
|
||||||
|
enabled: !Audio.muted
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
text = Math.round(Audio.volume * 100).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Audio
|
||||||
|
function onVolumeChanged() {
|
||||||
|
if (!outputVolumeInput.activeFocus) {
|
||||||
|
outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
if (activeFocus) {
|
||||||
|
const val = parseInt(text);
|
||||||
|
if (!isNaN(val) && val >= 0 && val <= 100) {
|
||||||
|
Audio.setVolume(val / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onEditingFinished: {
|
||||||
|
const val = parseInt(text);
|
||||||
|
if (isNaN(val) || val < 0 || val > 100) {
|
||||||
|
text = Math.round(Audio.volume * 100).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "%"
|
||||||
|
color: Colours.palette.m3outline
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
opacity: Audio.muted ? 0.5 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
implicitWidth: implicitHeight
|
||||||
|
implicitHeight: muteIcon.implicitHeight + Appearance.padding.normal * 2
|
||||||
|
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
color: Audio.muted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
function onClicked(): void {
|
||||||
|
if (Audio.sink?.audio) {
|
||||||
|
Audio.sink.audio.muted = !Audio.sink.audio.muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: muteIcon
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: Audio.muted ? "volume_off" : "volume_up"
|
||||||
|
color: Audio.muted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTextField {
|
StyledSlider {
|
||||||
id: outputVolumeInput
|
id: outputVolumeSlider
|
||||||
anchors.centerIn: parent
|
Layout.fillWidth: true
|
||||||
width: parent.width - Appearance.padding.normal
|
implicitHeight: Appearance.padding.normal * 3
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
|
||||||
validator: IntValidator { bottom: 0; top: 100 }
|
value: Audio.volume
|
||||||
enabled: !Audio.muted
|
enabled: !Audio.muted
|
||||||
|
opacity: enabled ? 1 : 0.5
|
||||||
Component.onCompleted: {
|
onMoved: {
|
||||||
text = Math.round(Audio.volume * 100).toString();
|
Audio.setVolume(value);
|
||||||
}
|
if (!outputVolumeInput.activeFocus) {
|
||||||
|
outputVolumeInput.text = Math.round(value * 100).toString();
|
||||||
Connections {
|
|
||||||
target: Audio
|
|
||||||
function onVolumeChanged() {
|
|
||||||
if (!outputVolumeInput.activeFocus) {
|
|
||||||
outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
if (activeFocus) {
|
|
||||||
const val = parseInt(text);
|
|
||||||
if (!isNaN(val) && val >= 0 && val <= 100) {
|
|
||||||
Audio.setVolume(val / 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onEditingFinished: {
|
|
||||||
const val = parseInt(text);
|
|
||||||
if (isNaN(val) || val < 0 || val > 100) {
|
|
||||||
text = Math.round(Audio.volume * 100).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: "%"
|
|
||||||
color: Colours.palette.m3outline
|
|
||||||
font.pointSize: Appearance.font.size.normal
|
|
||||||
opacity: Audio.muted ? 0.5 : 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledRect {
|
|
||||||
implicitWidth: implicitHeight
|
|
||||||
implicitHeight: muteIcon.implicitHeight + Appearance.padding.normal * 2
|
|
||||||
|
|
||||||
radius: Appearance.rounding.normal
|
|
||||||
color: Audio.muted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
function onClicked(): void {
|
|
||||||
if (Audio.sink?.audio) {
|
|
||||||
Audio.sink.audio.muted = !Audio.sink.audio.muted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
id: muteIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: Audio.muted ? "volume_off" : "volume_up"
|
|
||||||
color: Audio.muted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledSlider {
|
SectionHeader {
|
||||||
id: outputVolumeSlider
|
title: qsTr("Input volume")
|
||||||
Layout.fillWidth: true
|
description: qsTr("Control the volume of your input device")
|
||||||
implicitHeight: Appearance.padding.normal * 3
|
|
||||||
|
|
||||||
value: Audio.volume
|
|
||||||
enabled: !Audio.muted
|
|
||||||
opacity: enabled ? 1 : 0.5
|
|
||||||
onMoved: {
|
|
||||||
Audio.setVolume(value);
|
|
||||||
if (!outputVolumeInput.activeFocus) {
|
|
||||||
outputVolumeInput.text = Math.round(value * 100).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionHeader {
|
SectionContainer {
|
||||||
title: qsTr("Input volume")
|
contentSpacing: Appearance.spacing.normal
|
||||||
description: qsTr("Control the volume of your input device")
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionContainer {
|
ColumnLayout {
|
||||||
contentSpacing: Appearance.spacing.normal
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: Appearance.spacing.small
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: Appearance.spacing.normal
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: qsTr("Volume")
|
|
||||||
font.pointSize: Appearance.font.size.normal
|
|
||||||
font.weight: 500
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
StyledRect {
|
RowLayout {
|
||||||
Layout.preferredWidth: 70
|
Layout.fillWidth: true
|
||||||
implicitHeight: inputVolumeInput.implicitHeight + Appearance.padding.small * 2
|
spacing: Appearance.spacing.normal
|
||||||
color: inputVolumeInputHover.containsMouse || inputVolumeInput.activeFocus
|
|
||||||
? Colours.layer(Colours.palette.m3surfaceContainer, 3)
|
|
||||||
: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
border.width: 1
|
|
||||||
border.color: inputVolumeInput.activeFocus
|
|
||||||
? Colours.palette.m3primary
|
|
||||||
: Qt.alpha(Colours.palette.m3outline, 0.3)
|
|
||||||
enabled: !Audio.sourceMuted
|
|
||||||
opacity: enabled ? 1 : 0.5
|
|
||||||
|
|
||||||
Behavior on color { CAnim {} }
|
StyledText {
|
||||||
Behavior on border.color { CAnim {} }
|
text: qsTr("Volume")
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
Item {
|
||||||
id: inputVolumeInputHover
|
Layout.fillWidth: true
|
||||||
anchors.fill: parent
|
}
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.IBeamCursor
|
StyledRect {
|
||||||
acceptedButtons: Qt.NoButton
|
Layout.preferredWidth: 70
|
||||||
|
implicitHeight: inputVolumeInput.implicitHeight + Appearance.padding.small * 2
|
||||||
|
color: inputVolumeInputHover.containsMouse || inputVolumeInput.activeFocus
|
||||||
|
? Colours.layer(Colours.palette.m3surfaceContainer, 3)
|
||||||
|
: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
border.width: 1
|
||||||
|
border.color: inputVolumeInput.activeFocus
|
||||||
|
? Colours.palette.m3primary
|
||||||
|
: Qt.alpha(Colours.palette.m3outline, 0.3)
|
||||||
|
enabled: !Audio.sourceMuted
|
||||||
|
opacity: enabled ? 1 : 0.5
|
||||||
|
|
||||||
|
Behavior on color { CAnim {} }
|
||||||
|
Behavior on border.color { CAnim {} }
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: inputVolumeInputHover
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.IBeamCursor
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledTextField {
|
||||||
|
id: inputVolumeInput
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Appearance.padding.normal
|
||||||
|
horizontalAlignment: TextInput.AlignHCenter
|
||||||
|
validator: IntValidator { bottom: 0; top: 100 }
|
||||||
|
enabled: !Audio.sourceMuted
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
text = Math.round(Audio.sourceVolume * 100).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Audio
|
||||||
|
function onSourceVolumeChanged() {
|
||||||
|
if (!inputVolumeInput.activeFocus) {
|
||||||
|
inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
if (activeFocus) {
|
||||||
|
const val = parseInt(text);
|
||||||
|
if (!isNaN(val) && val >= 0 && val <= 100) {
|
||||||
|
Audio.setSourceVolume(val / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onEditingFinished: {
|
||||||
|
const val = parseInt(text);
|
||||||
|
if (isNaN(val) || val < 0 || val > 100) {
|
||||||
|
text = Math.round(Audio.sourceVolume * 100).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "%"
|
||||||
|
color: Colours.palette.m3outline
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
opacity: Audio.sourceMuted ? 0.5 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
implicitWidth: implicitHeight
|
||||||
|
implicitHeight: muteInputIcon.implicitHeight + Appearance.padding.normal * 2
|
||||||
|
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
color: Audio.sourceMuted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
function onClicked(): void {
|
||||||
|
if (Audio.source?.audio) {
|
||||||
|
Audio.source.audio.muted = !Audio.source.audio.muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: muteInputIcon
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "mic_off"
|
||||||
|
color: Audio.sourceMuted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTextField {
|
StyledSlider {
|
||||||
id: inputVolumeInput
|
id: inputVolumeSlider
|
||||||
anchors.centerIn: parent
|
Layout.fillWidth: true
|
||||||
width: parent.width - Appearance.padding.normal
|
implicitHeight: Appearance.padding.normal * 3
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
|
||||||
validator: IntValidator { bottom: 0; top: 100 }
|
value: Audio.sourceVolume
|
||||||
enabled: !Audio.sourceMuted
|
enabled: !Audio.sourceMuted
|
||||||
|
opacity: enabled ? 1 : 0.5
|
||||||
Component.onCompleted: {
|
onMoved: {
|
||||||
text = Math.round(Audio.sourceVolume * 100).toString();
|
Audio.setSourceVolume(value);
|
||||||
}
|
if (!inputVolumeInput.activeFocus) {
|
||||||
|
inputVolumeInput.text = Math.round(value * 100).toString();
|
||||||
Connections {
|
|
||||||
target: Audio
|
|
||||||
function onSourceVolumeChanged() {
|
|
||||||
if (!inputVolumeInput.activeFocus) {
|
|
||||||
inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
if (activeFocus) {
|
|
||||||
const val = parseInt(text);
|
|
||||||
if (!isNaN(val) && val >= 0 && val <= 100) {
|
|
||||||
Audio.setSourceVolume(val / 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onEditingFinished: {
|
|
||||||
const val = parseInt(text);
|
|
||||||
if (isNaN(val) || val < 0 || val > 100) {
|
|
||||||
text = Math.round(Audio.sourceVolume * 100).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: "%"
|
|
||||||
color: Colours.palette.m3outline
|
|
||||||
font.pointSize: Appearance.font.size.normal
|
|
||||||
opacity: Audio.sourceMuted ? 0.5 : 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledRect {
|
|
||||||
implicitWidth: implicitHeight
|
|
||||||
implicitHeight: muteInputIcon.implicitHeight + Appearance.padding.normal * 2
|
|
||||||
|
|
||||||
radius: Appearance.rounding.normal
|
|
||||||
color: Audio.sourceMuted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
function onClicked(): void {
|
|
||||||
if (Audio.source?.audio) {
|
|
||||||
Audio.source.audio.muted = !Audio.source.audio.muted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
id: muteInputIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "mic_off"
|
|
||||||
color: Audio.sourceMuted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledSlider {
|
|
||||||
id: inputVolumeSlider
|
|
||||||
Layout.fillWidth: true
|
|
||||||
implicitHeight: Appearance.padding.normal * 3
|
|
||||||
|
|
||||||
value: Audio.sourceVolume
|
|
||||||
enabled: !Audio.sourceMuted
|
|
||||||
opacity: enabled ? 1 : 0.5
|
|
||||||
onMoved: {
|
|
||||||
Audio.setSourceVolume(value);
|
|
||||||
if (!inputVolumeInput.activeFocus) {
|
|
||||||
inputVolumeInput.text = Math.round(value * 100).toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
|
import "../components"
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
import qs.components.effects
|
import qs.components.effects
|
||||||
import qs.components.containers
|
import qs.components.containers
|
||||||
|
|
@ -10,95 +11,50 @@ import Quickshell.Bluetooth
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
RowLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Session session
|
required property Session session
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: 0
|
SplitPaneLayout {
|
||||||
|
anchors.fill: parent
|
||||||
Item {
|
|
||||||
id: leftBtItem
|
|
||||||
Layout.preferredWidth: Math.floor(parent.width * 0.4)
|
|
||||||
Layout.minimumWidth: 420
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: leftBtClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: leftBtBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: leftBtLoader
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
|
||||||
anchors.leftMargin: Appearance.padding.large
|
|
||||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
sourceComponent: btDeviceListComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerBorder {
|
|
||||||
id: leftBtBorder
|
|
||||||
leftThickness: 0
|
|
||||||
rightThickness: Appearance.padding.normal / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: btDeviceListComponent
|
|
||||||
|
|
||||||
|
leftContent: Component {
|
||||||
DeviceList {
|
DeviceList {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
session: root.session
|
session: root.session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
rightContent: Component {
|
||||||
id: rightBtItem
|
Item {
|
||||||
Layout.fillWidth: true
|
id: rightBtPane
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: btClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: rightBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: loader
|
|
||||||
|
|
||||||
property BluetoothDevice pane: root.session.bt.active
|
property BluetoothDevice pane: root.session.bt.active
|
||||||
|
|
||||||
anchors.fill: parent
|
Loader {
|
||||||
anchors.margins: Appearance.padding.large * 2
|
id: rightLoader
|
||||||
|
|
||||||
asynchronous: true
|
anchors.fill: parent
|
||||||
sourceComponent: pane ? details : settings
|
anchors.margins: Appearance.padding.large * 2
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
sourceComponent: rightBtPane.pane ? details : settings
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on pane {
|
Behavior on pane {
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
|
target: rightLoader
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
to: 0
|
to: 0
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||||
}
|
}
|
||||||
Anim {
|
Anim {
|
||||||
|
target: rightLoader
|
||||||
property: "scale"
|
property: "scale"
|
||||||
to: 0.8
|
to: 0.8
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||||
|
|
@ -107,11 +63,13 @@ RowLayout {
|
||||||
PropertyAction {}
|
PropertyAction {}
|
||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
|
target: rightLoader
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
to: 1
|
to: 1
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||||
}
|
}
|
||||||
Anim {
|
Anim {
|
||||||
|
target: rightLoader
|
||||||
property: "scale"
|
property: "scale"
|
||||||
to: 1
|
to: 1
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||||
|
|
@ -119,49 +77,49 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerBorder {
|
Connections {
|
||||||
id: rightBorder
|
target: root.session.bt
|
||||||
|
function onActiveChanged() {
|
||||||
leftThickness: Appearance.padding.normal / 2
|
rightBtPane.pane = root.session.bt.active;
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: settings
|
|
||||||
|
|
||||||
StyledFlickable {
|
|
||||||
id: settingsFlickable
|
|
||||||
flickableDirection: Flickable.VerticalFlick
|
|
||||||
contentHeight: settingsInner.height
|
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
|
||||||
flickable: settingsFlickable
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings {
|
|
||||||
id: settingsInner
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
session: root.session
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: details
|
id: settings
|
||||||
|
|
||||||
Details {
|
StyledFlickable {
|
||||||
|
id: settingsFlickable
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: settingsInner.height
|
||||||
|
|
||||||
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
|
flickable: settingsFlickable
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings {
|
||||||
|
id: settingsInner
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
session: root.session
|
session: root.session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: details
|
||||||
|
|
||||||
|
Details {
|
||||||
|
session: root.session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component Anim: NumberAnimation {
|
component Anim: NumberAnimation {
|
||||||
target: loader
|
|
||||||
duration: Appearance.anim.durations.normal / 2
|
duration: Appearance.anim.durations.normal / 2
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
}
|
}
|
||||||
|
|
|
||||||
120
modules/controlcenter/components/SplitPaneLayout.qml
Normal file
120
modules/controlcenter/components/SplitPaneLayout.qml
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import qs.components
|
||||||
|
import qs.components.effects
|
||||||
|
import qs.config
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
property Component leftContent: null
|
||||||
|
property Component rightContent: null
|
||||||
|
|
||||||
|
// Left pane configuration
|
||||||
|
property real leftWidthRatio: 0.4
|
||||||
|
property int leftMinimumWidth: 420
|
||||||
|
property var leftLoaderProperties: ({})
|
||||||
|
|
||||||
|
// Right pane configuration
|
||||||
|
property var rightLoaderProperties: ({})
|
||||||
|
|
||||||
|
// Expose loaders for customization (access via splitLayout.leftLoader or splitLayout.rightLoader)
|
||||||
|
property alias leftLoader: leftLoader
|
||||||
|
property alias rightLoader: rightLoader
|
||||||
|
|
||||||
|
// Left pane
|
||||||
|
Item {
|
||||||
|
id: leftPane
|
||||||
|
|
||||||
|
Layout.preferredWidth: Math.floor(parent.width * root.leftWidthRatio)
|
||||||
|
Layout.minimumWidth: root.leftMinimumWidth
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
ClippingRectangle {
|
||||||
|
id: leftClippingRect
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.normal
|
||||||
|
anchors.leftMargin: 0
|
||||||
|
anchors.rightMargin: Appearance.padding.normal / 2
|
||||||
|
|
||||||
|
radius: leftBorder.innerRadius
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: leftLoader
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
||||||
|
anchors.leftMargin: Appearance.padding.large
|
||||||
|
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
sourceComponent: root.leftContent
|
||||||
|
|
||||||
|
// Apply any additional properties from leftLoaderProperties
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (const key in root.leftLoaderProperties) {
|
||||||
|
leftLoader[key] = root.leftLoaderProperties[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InnerBorder {
|
||||||
|
id: leftBorder
|
||||||
|
|
||||||
|
leftThickness: 0
|
||||||
|
rightThickness: Appearance.padding.normal / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right pane
|
||||||
|
Item {
|
||||||
|
id: rightPane
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
ClippingRectangle {
|
||||||
|
id: rightClippingRect
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.normal
|
||||||
|
anchors.leftMargin: 0
|
||||||
|
anchors.rightMargin: Appearance.padding.normal / 2
|
||||||
|
|
||||||
|
radius: rightBorder.innerRadius
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: rightLoader
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.large * 2
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
sourceComponent: root.rightContent
|
||||||
|
|
||||||
|
// Apply any additional properties from rightLoaderProperties
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (const key in root.rightLoaderProperties) {
|
||||||
|
rightLoader[key] = root.rightLoaderProperties[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InnerBorder {
|
||||||
|
id: rightBorder
|
||||||
|
|
||||||
|
leftThickness: Appearance.padding.normal / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
|
import "../components"
|
||||||
import "../../launcher/services"
|
import "../../launcher/services"
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
|
|
@ -16,7 +17,7 @@ import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import "../../../utils/scripts/fuzzysort.js" as Fuzzy
|
import "../../../utils/scripts/fuzzysort.js" as Fuzzy
|
||||||
|
|
||||||
RowLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Session session
|
required property Session session
|
||||||
|
|
@ -26,8 +27,6 @@ RowLayout {
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
onSelectedAppChanged: {
|
onSelectedAppChanged: {
|
||||||
root.session.launcher.active = root.selectedApp;
|
root.session.launcher.active = root.selectedApp;
|
||||||
updateToggleState();
|
updateToggleState();
|
||||||
|
|
@ -156,43 +155,10 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
SplitPaneLayout {
|
||||||
id: leftLauncherItem
|
anchors.fill: parent
|
||||||
Layout.preferredWidth: Math.floor(parent.width * 0.4)
|
|
||||||
Layout.minimumWidth: 420
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
leftContent: Component {
|
||||||
id: leftLauncherClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: leftLauncherBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: leftLauncherLoader
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
|
||||||
anchors.leftMargin: Appearance.padding.large
|
|
||||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
sourceComponent: leftContentComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerBorder {
|
|
||||||
id: leftLauncherBorder
|
|
||||||
leftThickness: 0
|
|
||||||
rightThickness: Appearance.padding.normal / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: leftContentComponent
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: leftLauncherLayout
|
id: leftLauncherLayout
|
||||||
|
|
@ -336,7 +302,8 @@ RowLayout {
|
||||||
// Lazy load: activate when left pane is loaded
|
// Lazy load: activate when left pane is loaded
|
||||||
// The ListView will load asynchronously, and search will work because filteredApps
|
// The ListView will load asynchronously, and search will work because filteredApps
|
||||||
// is updated regardless of whether the ListView is loaded
|
// is updated regardless of whether the ListView is loaded
|
||||||
return leftLauncherLoader.item !== null;
|
// Access loader through parent - this will be set when component loads
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceComponent: StyledListView {
|
sourceComponent: StyledListView {
|
||||||
|
|
@ -412,25 +379,10 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
rightContent: Component {
|
||||||
id: rightLauncherItem
|
Item {
|
||||||
Layout.fillWidth: true
|
id: rightLauncherPane
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: rightLauncherClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: rightLauncherBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: rightLauncherLoader
|
|
||||||
|
|
||||||
property var pane: root.session.launcher.active
|
property var pane: root.session.launcher.active
|
||||||
property string paneId: pane ? (pane.id || pane.entry?.id || "") : ""
|
property string paneId: pane ? (pane.id || pane.entry?.id || "") : ""
|
||||||
|
|
@ -442,28 +394,34 @@ RowLayout {
|
||||||
return pane ? appDetails : settings;
|
return pane ? appDetails : settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.large * 2
|
|
||||||
|
|
||||||
opacity: 1
|
|
||||||
scale: 1
|
|
||||||
transformOrigin: Item.Center
|
|
||||||
clip: false
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
sourceComponent: rightLauncherLoader.targetComponent
|
|
||||||
active: true
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
displayedApp = pane;
|
displayedApp = pane;
|
||||||
targetComponent = getComponentForPane();
|
targetComponent = getComponentForPane();
|
||||||
nextComponent = targetComponent;
|
nextComponent = targetComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemChanged: {
|
Loader {
|
||||||
// Ensure displayedApp is set when item is created (for async loading)
|
id: rightLauncherLoader
|
||||||
if (item && pane && displayedApp !== pane) {
|
|
||||||
displayedApp = pane;
|
anchors.fill: parent
|
||||||
|
|
||||||
|
opacity: 1
|
||||||
|
scale: 1
|
||||||
|
transformOrigin: Item.Center
|
||||||
|
clip: false
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
sourceComponent: rightLauncherPane.targetComponent
|
||||||
|
active: true
|
||||||
|
|
||||||
|
// Expose displayedApp to loaded components
|
||||||
|
property var displayedApp: rightLauncherPane.displayedApp
|
||||||
|
|
||||||
|
onItemChanged: {
|
||||||
|
// Ensure displayedApp is set when item is created (for async loading)
|
||||||
|
if (item && rightLauncherPane.pane && rightLauncherPane.displayedApp !== rightLauncherPane.pane) {
|
||||||
|
rightLauncherPane.displayedApp = rightLauncherPane.pane;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,9 +442,9 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: rightLauncherLoader
|
target: rightLauncherPane
|
||||||
property: "displayedApp"
|
property: "displayedApp"
|
||||||
value: rightLauncherLoader.pane
|
value: rightLauncherPane.pane
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: rightLauncherLoader
|
target: rightLauncherLoader
|
||||||
|
|
@ -494,9 +452,9 @@ RowLayout {
|
||||||
value: false
|
value: false
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: rightLauncherLoader
|
target: rightLauncherPane
|
||||||
property: "targetComponent"
|
property: "targetComponent"
|
||||||
value: rightLauncherLoader.nextComponent
|
value: rightLauncherPane.nextComponent
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: rightLauncherLoader
|
target: rightLauncherLoader
|
||||||
|
|
@ -539,90 +497,90 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InnerBorder {
|
Component {
|
||||||
id: rightLauncherBorder
|
id: settings
|
||||||
|
|
||||||
leftThickness: Appearance.padding.normal / 2
|
StyledFlickable {
|
||||||
}
|
id: settingsFlickable
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: settingsInner.height
|
||||||
|
|
||||||
Component {
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
id: settings
|
flickable: settingsFlickable
|
||||||
|
}
|
||||||
|
|
||||||
StyledFlickable {
|
Settings {
|
||||||
id: settingsFlickable
|
id: settingsInner
|
||||||
flickableDirection: Flickable.VerticalFlick
|
|
||||||
contentHeight: settingsInner.height
|
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
anchors.left: parent.left
|
||||||
flickable: settingsFlickable
|
anchors.right: parent.right
|
||||||
}
|
anchors.top: parent.top
|
||||||
|
session: root.session
|
||||||
Settings {
|
|
||||||
id: settingsInner
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
session: root.session
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: appDetails
|
id: appDetails
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
id: appDetailsLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: Appearance.spacing.normal
|
// Get displayedApp from parent Loader (the Loader has displayedApp property we set)
|
||||||
|
readonly property var displayedApp: parent && parent.displayedApp !== undefined ? parent.displayedApp : null
|
||||||
|
|
||||||
Item {
|
spacing: Appearance.spacing.normal
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
Layout.leftMargin: Appearance.padding.large * 2
|
|
||||||
Layout.rightMargin: Appearance.padding.large * 2
|
|
||||||
Layout.topMargin: Appearance.padding.large * 2
|
|
||||||
implicitWidth: iconLoader.implicitWidth
|
|
||||||
implicitHeight: iconLoader.implicitHeight
|
|
||||||
|
|
||||||
Loader {
|
Item {
|
||||||
id: iconLoader
|
Layout.alignment: Qt.AlignHCenter
|
||||||
sourceComponent: rightLauncherLoader.displayedApp ? appIconComponent : defaultIconComponent
|
Layout.leftMargin: Appearance.padding.large * 2
|
||||||
}
|
Layout.rightMargin: Appearance.padding.large * 2
|
||||||
|
Layout.topMargin: Appearance.padding.large * 2
|
||||||
|
implicitWidth: iconLoader.implicitWidth
|
||||||
|
implicitHeight: iconLoader.implicitHeight
|
||||||
|
|
||||||
Component {
|
Loader {
|
||||||
id: appIconComponent
|
id: iconLoader
|
||||||
IconImage {
|
sourceComponent: parent.parent.displayedApp ? appIconComponent : defaultIconComponent
|
||||||
implicitSize: Appearance.font.size.extraLarge * 3 * 2
|
}
|
||||||
source: {
|
|
||||||
if (!rightLauncherLoader.displayedApp) return "image-missing";
|
Component {
|
||||||
const entry = rightLauncherLoader.displayedApp.entry;
|
id: appIconComponent
|
||||||
if (entry && entry.icon) {
|
IconImage {
|
||||||
return Quickshell.iconPath(entry.icon, "image-missing");
|
implicitSize: Appearance.font.size.extraLarge * 3 * 2
|
||||||
}
|
source: {
|
||||||
return "image-missing";
|
const app = iconLoader.parent.parent.displayedApp;
|
||||||
|
if (!app) return "image-missing";
|
||||||
|
const entry = app.entry;
|
||||||
|
if (entry && entry.icon) {
|
||||||
|
return Quickshell.iconPath(entry.icon, "image-missing");
|
||||||
}
|
}
|
||||||
}
|
return "image-missing";
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: defaultIconComponent
|
|
||||||
MaterialIcon {
|
|
||||||
text: "apps"
|
|
||||||
font.pointSize: Appearance.font.size.extraLarge * 3
|
|
||||||
font.bold: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
Component {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
id: defaultIconComponent
|
||||||
Layout.leftMargin: Appearance.padding.large * 2
|
MaterialIcon {
|
||||||
Layout.rightMargin: Appearance.padding.large * 2
|
text: "apps"
|
||||||
text: rightLauncherLoader.displayedApp ? (rightLauncherLoader.displayedApp.name || rightLauncherLoader.displayedApp.entry?.name || qsTr("Application Details")) : qsTr("Launcher Applications")
|
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||||
font.pointSize: Appearance.font.size.large
|
font.bold: true
|
||||||
font.bold: true
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.leftMargin: Appearance.padding.large * 2
|
||||||
|
Layout.rightMargin: Appearance.padding.large * 2
|
||||||
|
text: displayedApp ? (displayedApp.name || displayedApp.entry?.name || qsTr("Application Details")) : qsTr("Launcher Applications")
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -648,38 +606,38 @@ RowLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
spacing: Appearance.spacing.normal
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
SwitchRow {
|
SwitchRow {
|
||||||
Layout.topMargin: Appearance.spacing.normal
|
Layout.topMargin: Appearance.spacing.normal
|
||||||
visible: rightLauncherLoader.displayedApp !== null
|
visible: appDetailsLayout.displayedApp !== null
|
||||||
label: qsTr("Hide from launcher")
|
label: qsTr("Hide from launcher")
|
||||||
checked: root.hideFromLauncherChecked
|
checked: root.hideFromLauncherChecked
|
||||||
enabled: rightLauncherLoader.displayedApp !== null
|
enabled: appDetailsLayout.displayedApp !== null
|
||||||
onToggled: checked => {
|
onToggled: checked => {
|
||||||
root.hideFromLauncherChecked = checked;
|
root.hideFromLauncherChecked = checked;
|
||||||
if (rightLauncherLoader.displayedApp) {
|
const app = appDetailsLayout.displayedApp;
|
||||||
const appId = rightLauncherLoader.displayedApp.id || rightLauncherLoader.displayedApp.entry?.id;
|
if (app) {
|
||||||
const hiddenApps = Config.launcher.hiddenApps ? [...Config.launcher.hiddenApps] : [];
|
const appId = app.id || app.entry?.id;
|
||||||
if (checked) {
|
const hiddenApps = Config.launcher.hiddenApps ? [...Config.launcher.hiddenApps] : [];
|
||||||
if (!hiddenApps.includes(appId)) {
|
if (checked) {
|
||||||
hiddenApps.push(appId);
|
if (!hiddenApps.includes(appId)) {
|
||||||
}
|
hiddenApps.push(appId);
|
||||||
} else {
|
}
|
||||||
const index = hiddenApps.indexOf(appId);
|
} else {
|
||||||
if (index !== -1) {
|
const index = hiddenApps.indexOf(appId);
|
||||||
hiddenApps.splice(index, 1);
|
if (index !== -1) {
|
||||||
}
|
hiddenApps.splice(index, 1);
|
||||||
}
|
}
|
||||||
Config.launcher.hiddenApps = hiddenApps;
|
|
||||||
Config.save();
|
|
||||||
}
|
}
|
||||||
|
Config.launcher.hiddenApps = hiddenApps;
|
||||||
|
Config.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
component Anim: NumberAnimation {
|
component Anim: NumberAnimation {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
|
import "../components"
|
||||||
import "."
|
import "."
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
|
|
@ -21,49 +22,12 @@ Item {
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
RowLayout {
|
SplitPaneLayout {
|
||||||
id: contentLayout
|
id: splitLayout
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Item {
|
leftContent: Component {
|
||||||
id: leftNetworkItem
|
|
||||||
Layout.preferredWidth: Math.floor(parent.width * 0.4)
|
|
||||||
Layout.minimumWidth: 420
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: leftNetworkClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: leftNetworkBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: leftNetworkLoader
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
|
||||||
anchors.leftMargin: Appearance.padding.large
|
|
||||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
sourceComponent: networkListComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerBorder {
|
|
||||||
id: leftNetworkBorder
|
|
||||||
leftThickness: 0
|
|
||||||
rightThickness: Appearance.padding.normal / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: networkListComponent
|
|
||||||
|
|
||||||
StyledFlickable {
|
StyledFlickable {
|
||||||
id: leftFlickable
|
id: leftFlickable
|
||||||
|
|
@ -473,38 +437,47 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
rightContent: Component {
|
||||||
id: rightNetworkItem
|
Item {
|
||||||
Layout.fillWidth: true
|
id: rightPaneItem
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
id: networkClippingRect
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.rightMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
radius: rightBorder.innerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
// Right pane - networking details/settings
|
// Right pane - networking details/settings
|
||||||
Loader {
|
property var ethernetPane: root.session.ethernet.active
|
||||||
id: loader
|
property var wirelessPane: root.session.network.active
|
||||||
|
property var pane: ethernetPane || wirelessPane
|
||||||
|
property string paneId: ethernetPane ? (ethernetPane.interface || "") : (wirelessPane ? (wirelessPane.ssid || wirelessPane.bssid || "") : "")
|
||||||
|
property Component targetComponent: settings
|
||||||
|
property Component nextComponent: settings
|
||||||
|
|
||||||
property var ethernetPane: root.session.ethernet.active
|
function getComponentForPane() {
|
||||||
property var wirelessPane: root.session.network.active
|
return pane ? (ethernetPane ? ethernetDetails : wirelessDetails) : settings;
|
||||||
property var pane: ethernetPane || wirelessPane
|
}
|
||||||
property string paneId: ethernetPane ? (ethernetPane.interface || "") : (wirelessPane ? (wirelessPane.ssid || wirelessPane.bssid || "") : "")
|
|
||||||
property Component targetComponent: settings
|
|
||||||
property Component nextComponent: settings
|
|
||||||
|
|
||||||
function getComponentForPane() {
|
Component.onCompleted: {
|
||||||
return pane ? (ethernetPane ? ethernetDetails : wirelessDetails) : settings;
|
targetComponent = getComponentForPane();
|
||||||
|
nextComponent = targetComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.session.ethernet
|
||||||
|
function onActiveChanged() {
|
||||||
|
nextComponent = getComponentForPane();
|
||||||
|
paneId = ethernetPane ? (ethernetPane.interface || "") : (wirelessPane ? (wirelessPane.ssid || wirelessPane.bssid || "") : "");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.session.network
|
||||||
|
function onActiveChanged() {
|
||||||
|
nextComponent = getComponentForPane();
|
||||||
|
paneId = ethernetPane ? (ethernetPane.interface || "") : (wirelessPane ? (wirelessPane.ssid || wirelessPane.bssid || "") : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: rightLoader
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Appearance.padding.large * 2
|
anchors.margins: Appearance.padding.large * 2
|
||||||
|
|
@ -515,131 +488,129 @@ Item {
|
||||||
clip: false
|
clip: false
|
||||||
|
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
sourceComponent: loader.targetComponent
|
sourceComponent: rightPaneItem.targetComponent
|
||||||
|
|
||||||
Component.onCompleted: {
|
Connections {
|
||||||
targetComponent = getComponentForPane();
|
target: rightPaneItem
|
||||||
nextComponent = targetComponent;
|
function onPaneIdChanged() {
|
||||||
|
rightPaneItem.targetComponent = rightPaneItem.nextComponent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on paneId {
|
Behavior on paneId {
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
target: loader
|
target: rightLoader
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
to: 0
|
to: 0
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: loader
|
|
||||||
property: "scale"
|
|
||||||
to: 0.8
|
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PropertyAction {
|
Anim {
|
||||||
target: loader
|
target: rightLoader
|
||||||
property: "targetComponent"
|
property: "scale"
|
||||||
value: loader.nextComponent
|
to: 0.8
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||||
}
|
}
|
||||||
ParallelAnimation {
|
}
|
||||||
Anim {
|
PropertyAction {
|
||||||
target: loader
|
target: rightPaneItem
|
||||||
property: "opacity"
|
property: "targetComponent"
|
||||||
to: 1
|
value: rightPaneItem.nextComponent
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
}
|
||||||
}
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
target: loader
|
target: rightLoader
|
||||||
property: "scale"
|
property: "opacity"
|
||||||
to: 1
|
to: 1
|
||||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||||
}
|
}
|
||||||
|
Anim {
|
||||||
|
target: rightLoader
|
||||||
|
property: "scale"
|
||||||
|
to: 1
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onPaneChanged: {
|
Connections {
|
||||||
nextComponent = getComponentForPane();
|
target: rightPaneItem
|
||||||
paneId = ethernetPane ? (ethernetPane.interface || "") : (wirelessPane ? (wirelessPane.ssid || wirelessPane.bssid || "") : "");
|
function onPaneIdChanged() {
|
||||||
|
rightPaneItem.targetComponent = rightPaneItem.nextComponent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InnerBorder {
|
Component {
|
||||||
id: rightBorder
|
id: settings
|
||||||
|
|
||||||
leftThickness: Appearance.padding.normal / 2
|
StyledFlickable {
|
||||||
|
id: settingsFlickable
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: settingsInner.height
|
||||||
|
|
||||||
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
|
flickable: settingsFlickable
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
NetworkSettings {
|
||||||
id: settings
|
id: settingsInner
|
||||||
|
|
||||||
StyledFlickable {
|
anchors.left: parent.left
|
||||||
id: settingsFlickable
|
anchors.right: parent.right
|
||||||
flickableDirection: Flickable.VerticalFlick
|
anchors.top: parent.top
|
||||||
contentHeight: settingsInner.height
|
session: root.session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
Component {
|
||||||
flickable: settingsFlickable
|
id: ethernetDetails
|
||||||
}
|
|
||||||
|
|
||||||
NetworkSettings {
|
StyledFlickable {
|
||||||
id: settingsInner
|
id: ethernetFlickable
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: ethernetDetailsInner.height
|
||||||
|
|
||||||
anchors.left: parent.left
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
anchors.right: parent.right
|
flickable: ethernetFlickable
|
||||||
anchors.top: parent.top
|
|
||||||
session: root.session
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
EthernetDetails {
|
||||||
id: ethernetDetails
|
id: ethernetDetailsInner
|
||||||
|
|
||||||
StyledFlickable {
|
anchors.left: parent.left
|
||||||
id: ethernetFlickable
|
anchors.right: parent.right
|
||||||
flickableDirection: Flickable.VerticalFlick
|
anchors.top: parent.top
|
||||||
contentHeight: ethernetDetailsInner.height
|
session: root.session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
Component {
|
||||||
flickable: ethernetFlickable
|
id: wirelessDetails
|
||||||
}
|
|
||||||
|
|
||||||
EthernetDetails {
|
StyledFlickable {
|
||||||
id: ethernetDetailsInner
|
id: wirelessFlickable
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: wirelessDetailsInner.height
|
||||||
|
|
||||||
anchors.left: parent.left
|
StyledScrollBar.vertical: StyledScrollBar {
|
||||||
anchors.right: parent.right
|
flickable: wirelessFlickable
|
||||||
anchors.top: parent.top
|
|
||||||
session: root.session
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
WirelessDetails {
|
||||||
id: wirelessDetails
|
id: wirelessDetailsInner
|
||||||
|
|
||||||
StyledFlickable {
|
anchors.left: parent.left
|
||||||
id: wirelessFlickable
|
anchors.right: parent.right
|
||||||
flickableDirection: Flickable.VerticalFlick
|
anchors.top: parent.top
|
||||||
contentHeight: wirelessDetailsInner.height
|
session: root.session
|
||||||
|
|
||||||
StyledScrollBar.vertical: StyledScrollBar {
|
|
||||||
flickable: wirelessFlickable
|
|
||||||
}
|
|
||||||
|
|
||||||
WirelessDetails {
|
|
||||||
id: wirelessDetailsInner
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
session: root.session
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -651,7 +622,6 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
component Anim: NumberAnimation {
|
component Anim: NumberAnimation {
|
||||||
target: loader
|
|
||||||
duration: Appearance.anim.durations.normal / 2
|
duration: Appearance.anim.durations.normal / 2
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue