Feature: Make home UniFi VPN row a collapsible card
Put the Replace config option behind an expand chevron, like Mullvad's options, and frame the card while it's expanded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,9 @@ Item {
|
|||||||
property string protonActionStatus: ""
|
property string protonActionStatus: ""
|
||||||
property string homeWgActionStatus: ""
|
property string homeWgActionStatus: ""
|
||||||
property bool homeWgImporting: homeWgImportProc.running
|
property bool homeWgImporting: homeWgImportProc.running
|
||||||
|
// Whether Home's options (Replace config) are expanded — kept across
|
||||||
|
// panel opens, like mullvadOptionsOpen.
|
||||||
|
property bool homeWgOptionsOpen: false
|
||||||
|
|
||||||
// --- Mullvad advanced options (auto-connect, relay location, multihop) --
|
// --- Mullvad advanced options (auto-connect, relay location, multihop) --
|
||||||
// ProtonVPN's CLI is plain-text-only and far less predictable across
|
// ProtonVPN's CLI is plain-text-only and far less predictable across
|
||||||
@@ -1006,7 +1009,124 @@ Item {
|
|||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 2
|
// Room for the cards' outlines (drawn 3px outside them)
|
||||||
|
// so two expanded ones don't touch.
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
// Same collapsible card as Mullvad below — framed only
|
||||||
|
// while its options (Replace config) are expanded.
|
||||||
|
Item {
|
||||||
|
readonly property bool _framed: root.homeWgOptionsOpen && root.homeWgInstalled
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: homeWgSectionColumn.implicitHeight
|
||||||
|
Behavior on implicitHeight {
|
||||||
|
NumberAnimation { duration: Appearance.animationDuration; easing.type: Easing.OutCubic }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outline offset outside the content rather than drawn on
|
||||||
|
// its own edge — same as Volume.qml's DeviceRow hover —
|
||||||
|
// so the row doesn't shift when the options open.
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: -3
|
||||||
|
radius: 0
|
||||||
|
color: "transparent"
|
||||||
|
border.color: Colors.foreground
|
||||||
|
border.width: parent._framed ? 1 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clipped separately so the outline above isn't.
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: homeWgSectionColumn
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
ProviderRow {
|
||||||
|
label: "Home (UniFi)"
|
||||||
|
subIcon: "home"
|
||||||
|
state: root.homeWgState
|
||||||
|
detailText: root.homeWgDetail
|
||||||
|
installed: root.homeWgInstalled
|
||||||
|
missingText: "Not set up"
|
||||||
|
expandable: root.homeWgInstalled
|
||||||
|
expanded: root.homeWgOptionsOpen
|
||||||
|
onToggle: root.toggleHomeWg()
|
||||||
|
onExpandToggle: root.homeWgOptionsOpen = !root.homeWgOptionsOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusLine { message: root.homeWgActionStatus }
|
||||||
|
|
||||||
|
// Imports (or replaces) the UniFi client .conf through a
|
||||||
|
// file chooser. Shown outright until a profile exists
|
||||||
|
// (so first-time setup isn't hidden behind the
|
||||||
|
// chevron), then only inside the expanded options.
|
||||||
|
// Hidden while connected — replacing deletes the
|
||||||
|
// profile, which would drop the tunnel.
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: importRow.implicitHeight + 8
|
||||||
|
visible: root.homeWgState === "disconnected"
|
||||||
|
&& (!root.homeWgInstalled || root.homeWgOptionsOpen)
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: importRow
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 34
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 4
|
||||||
|
opacity: root.homeWgImporting ? 0.5 : 1
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: root.homeWgInstalled ? "sync" : "upload_file"
|
||||||
|
font.family: Appearance.iconFontFamilyRounded
|
||||||
|
font.variableAxes: Appearance.iconFontAxes
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: importMouse.containsMouse ? Colors.foreground : Colors.primary
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: root.homeWgImporting ? "Choosing file…"
|
||||||
|
: root.homeWgInstalled ? "Replace config" : "Add config"
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
font.underline: importMouse.containsMouse
|
||||||
|
color: importMouse.containsMouse ? Colors.foreground : Colors.primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: importMouse
|
||||||
|
anchors.fill: importRow
|
||||||
|
anchors.margins: -4
|
||||||
|
enabled: !root.homeWgImporting
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.importHomeWgConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
x: 34
|
||||||
|
width: parent.width - x
|
||||||
|
visible: root.homeWgOptionsOpen && root.homeWgInstalled
|
||||||
|
&& root.homeWgState !== "disconnected"
|
||||||
|
text: "Disconnect to replace config"
|
||||||
|
bottomPadding: 6
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: Colors.muted
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mullvad's connect row and its advanced options share a
|
// Mullvad's connect row and its advanced options share a
|
||||||
// single bordered card — the border wraps the whole
|
// single bordered card — the border wraps the whole
|
||||||
@@ -1014,14 +1134,11 @@ Item {
|
|||||||
// grows to include the options/picker as they open,
|
// grows to include the options/picker as they open,
|
||||||
// rather than the options having a separate box of
|
// rather than the options having a separate box of
|
||||||
// their own below an unbordered connect row.
|
// their own below an unbordered connect row.
|
||||||
Rectangle {
|
// Only outlined while the options are expanded.
|
||||||
|
Item {
|
||||||
|
readonly property bool _framed: root.mullvadOptionsOpen && root.mullvadInstalled
|
||||||
width: parent.width
|
width: parent.width
|
||||||
radius: 0
|
implicitHeight: mullvadSectionColumn.implicitHeight
|
||||||
color: Colors.background
|
|
||||||
border.color: Colors.muted
|
|
||||||
border.width: 1
|
|
||||||
implicitHeight: mullvadSectionColumn.implicitHeight + 16
|
|
||||||
clip: true
|
|
||||||
// Without this, the card snapped to its new size
|
// Without this, the card snapped to its new size
|
||||||
// instantly while the popup around it was still
|
// instantly while the popup around it was still
|
||||||
// animating open, so the border visibly lagged
|
// animating open, so the border visibly lagged
|
||||||
@@ -1031,171 +1148,188 @@ Item {
|
|||||||
NumberAnimation { duration: Appearance.animationDuration; easing.type: Easing.OutCubic }
|
NumberAnimation { duration: Appearance.animationDuration; easing.type: Easing.OutCubic }
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
// Outline offset outside the content rather than drawn on
|
||||||
id: mullvadSectionColumn
|
// its own edge — same as Volume.qml's DeviceRow hover —
|
||||||
anchors.left: parent.left
|
// so the row doesn't shift when the options open.
|
||||||
anchors.right: parent.right
|
Rectangle {
|
||||||
anchors.top: parent.top
|
anchors.fill: parent
|
||||||
anchors.margins: 8
|
anchors.margins: -3
|
||||||
spacing: 8
|
radius: 0
|
||||||
|
color: "transparent"
|
||||||
|
border.color: Colors.foreground
|
||||||
|
border.width: parent._framed ? 1 : 0
|
||||||
|
}
|
||||||
|
|
||||||
ProviderRow {
|
// Clipped separately so the outline above isn't.
|
||||||
label: "Mullvad"
|
Item {
|
||||||
subIcon: "gpp_good"
|
anchors.fill: parent
|
||||||
state: root.mullvadState
|
clip: true
|
||||||
detailText: root.mullvadDetail
|
|
||||||
installed: root.mullvadInstalled
|
|
||||||
expandable: root.mullvadInstalled
|
|
||||||
expanded: root.mullvadOptionsOpen
|
|
||||||
onToggle: root.toggleMullvad()
|
|
||||||
onExpandToggle: root.openMullvadOptions()
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusLine { message: root.mullvadActionStatus }
|
|
||||||
|
|
||||||
// Advanced options — auto-connect, exit/entry
|
|
||||||
// relay location, multihop.
|
|
||||||
Column {
|
Column {
|
||||||
id: mullvadOptionsColumn
|
id: mullvadSectionColumn
|
||||||
width: parent.width
|
anchors.left: parent.left
|
||||||
visible: root.mullvadOptionsOpen && root.mullvadInstalled
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
RowLayout {
|
ProviderRow {
|
||||||
width: parent.width
|
label: "Mullvad"
|
||||||
Text {
|
subIcon: "gpp_good"
|
||||||
Layout.fillWidth: true
|
state: root.mullvadState
|
||||||
text: "Auto-connect"
|
detailText: root.mullvadDetail
|
||||||
font.family: Appearance.fontFamily
|
installed: root.mullvadInstalled
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
expandable: root.mullvadInstalled
|
||||||
color: Colors.foreground
|
expanded: root.mullvadOptionsOpen
|
||||||
|
onToggle: root.toggleMullvad()
|
||||||
|
onExpandToggle: root.openMullvadOptions()
|
||||||
}
|
}
|
||||||
ToggleSwitch {
|
|
||||||
checked: root.mullvadAutoConnect
|
|
||||||
busy: mullvadAutoConnectSetProc.running
|
|
||||||
onToggled: root.setMullvadAutoConnect(!root.mullvadAutoConnect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
StatusLine { message: root.mullvadActionStatus }
|
||||||
width: parent.width
|
|
||||||
Text {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: "Multihop"
|
|
||||||
font.family: Appearance.fontFamily
|
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
|
||||||
color: Colors.foreground
|
|
||||||
}
|
|
||||||
ToggleSwitch {
|
|
||||||
checked: root.mullvadMultihop
|
|
||||||
busy: mullvadRelaySetProc.running
|
|
||||||
onToggled: root.setMullvadMultihop(!root.mullvadMultihop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocationField {
|
// Advanced options — auto-connect, exit/entry
|
||||||
fieldLabel: root.mullvadMultihop ? "Exit" : "Location"
|
// relay location, multihop.
|
||||||
valueText: root.mullvadLocationLabel
|
Column {
|
||||||
open: root.mullvadPickerTarget === "exit"
|
id: mullvadOptionsColumn
|
||||||
onClicked: root.openMullvadPicker("exit")
|
|
||||||
}
|
|
||||||
|
|
||||||
LocationField {
|
|
||||||
visible: root.mullvadMultihop
|
|
||||||
fieldLabel: "Entry"
|
|
||||||
valueText: root.mullvadEntryLabel
|
|
||||||
open: root.mullvadPickerTarget === "entry"
|
|
||||||
onClicked: root.openMullvadPicker("entry")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shared country picker for whichever LocationField
|
|
||||||
// was last clicked — filter box plus a capped,
|
|
||||||
// scrollable list ("Any" always pinned first).
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
visible: root.mullvadPickerTarget !== ""
|
|
||||||
spacing: 6
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
implicitHeight: 24
|
visible: root.mullvadOptionsOpen && root.mullvadInstalled
|
||||||
radius: 0
|
spacing: 8
|
||||||
color: Colors.surface
|
|
||||||
border.color: Colors.muted
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
width: parent.width
|
||||||
Text {
|
Text {
|
||||||
anchors.fill: parent
|
Layout.fillWidth: true
|
||||||
anchors.margins: 6
|
text: "Auto-connect"
|
||||||
visible: mullvadFilterInput.text.length === 0
|
|
||||||
text: "Search country…"
|
|
||||||
font.family: Appearance.fontFamily
|
font.family: Appearance.fontFamily
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
color: Colors.muted
|
|
||||||
}
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: mullvadFilterInput
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 6
|
|
||||||
color: Colors.foreground
|
color: Colors.foreground
|
||||||
font.family: Appearance.fontFamily
|
}
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
ToggleSwitch {
|
||||||
clip: true
|
checked: root.mullvadAutoConnect
|
||||||
focus: root.mullvadPickerTarget !== ""
|
busy: mullvadAutoConnectSetProc.running
|
||||||
text: root.mullvadPickerFilter
|
onToggled: root.setMullvadAutoConnect(!root.mullvadAutoConnect)
|
||||||
onTextChanged: root.mullvadPickerFilter = text
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Flickable {
|
RowLayout {
|
||||||
id: mullvadPickerFlick
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Math.min(mullvadPickerColumn.implicitHeight, 150)
|
Text {
|
||||||
contentWidth: width
|
Layout.fillWidth: true
|
||||||
contentHeight: mullvadPickerColumn.implicitHeight
|
text: "Multihop"
|
||||||
clip: true
|
font.family: Appearance.fontFamily
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: Colors.foreground
|
||||||
|
}
|
||||||
|
ToggleSwitch {
|
||||||
|
checked: root.mullvadMultihop
|
||||||
|
busy: mullvadRelaySetProc.running
|
||||||
|
onToggled: root.setMullvadMultihop(!root.mullvadMultihop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
LocationField {
|
||||||
id: mullvadPickerColumn
|
fieldLabel: root.mullvadMultihop ? "Exit" : "Location"
|
||||||
width: mullvadPickerFlick.width
|
valueText: root.mullvadLocationLabel
|
||||||
spacing: 1
|
open: root.mullvadPickerTarget === "exit"
|
||||||
|
onClicked: root.openMullvadPicker("exit")
|
||||||
|
}
|
||||||
|
|
||||||
Repeater {
|
LocationField {
|
||||||
model: [{ name: "Any", code: "any" }].concat(root.mullvadFilteredCountries)
|
visible: root.mullvadMultihop
|
||||||
Rectangle {
|
fieldLabel: "Entry"
|
||||||
required property var modelData
|
valueText: root.mullvadEntryLabel
|
||||||
width: parent.width
|
open: root.mullvadPickerTarget === "entry"
|
||||||
implicitHeight: 22
|
onClicked: root.openMullvadPicker("entry")
|
||||||
radius: 0
|
}
|
||||||
color: countryMouse.containsMouse ? Colors.primary : "transparent"
|
|
||||||
|
|
||||||
Text {
|
// Shared country picker for whichever LocationField
|
||||||
anchors.left: parent.left
|
// was last clicked — filter box plus a capped,
|
||||||
anchors.right: parent.right
|
// scrollable list ("Any" always pinned first).
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
Column {
|
||||||
anchors.leftMargin: 4
|
width: parent.width
|
||||||
anchors.rightMargin: 4
|
visible: root.mullvadPickerTarget !== ""
|
||||||
elide: Text.ElideRight
|
spacing: 6
|
||||||
text: modelData.name
|
|
||||||
font.family: Appearance.fontFamily
|
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
|
||||||
color: countryMouse.containsMouse ? Colors.primaryText : Colors.foreground
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
Rectangle {
|
||||||
id: countryMouse
|
width: parent.width
|
||||||
anchors.fill: parent
|
implicitHeight: 24
|
||||||
hoverEnabled: true
|
radius: 0
|
||||||
cursorShape: Qt.PointingHandCursor
|
color: Colors.surface
|
||||||
onClicked: root.pickMullvadLocation(modelData.code)
|
border.color: Colors.muted
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 6
|
||||||
|
visible: mullvadFilterInput.text.length === 0
|
||||||
|
text: "Search country…"
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: Colors.muted
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
id: mullvadFilterInput
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 6
|
||||||
|
color: Colors.foreground
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
clip: true
|
||||||
|
focus: root.mullvadPickerTarget !== ""
|
||||||
|
text: root.mullvadPickerFilter
|
||||||
|
onTextChanged: root.mullvadPickerFilter = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: mullvadPickerFlick
|
||||||
|
width: parent.width
|
||||||
|
height: Math.min(mullvadPickerColumn.implicitHeight, 150)
|
||||||
|
contentWidth: width
|
||||||
|
contentHeight: mullvadPickerColumn.implicitHeight
|
||||||
|
clip: true
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: mullvadPickerColumn
|
||||||
|
width: mullvadPickerFlick.width
|
||||||
|
spacing: 1
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: [{ name: "Any", code: "any" }].concat(root.mullvadFilteredCountries)
|
||||||
|
Rectangle {
|
||||||
|
required property var modelData
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: 22
|
||||||
|
radius: 0
|
||||||
|
color: countryMouse.containsMouse ? Colors.primary : "transparent"
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.leftMargin: 4
|
||||||
|
anchors.rightMargin: 4
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: modelData.name
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: countryMouse.containsMouse ? Colors.primaryText : Colors.foreground
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: countryMouse
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.pickMullvadLocation(modelData.code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1210,64 +1344,6 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StatusLine { message: root.protonActionStatus }
|
StatusLine { message: root.protonActionStatus }
|
||||||
|
|
||||||
ProviderRow {
|
|
||||||
label: "Home (UniFi)"
|
|
||||||
subIcon: "home"
|
|
||||||
state: root.homeWgState
|
|
||||||
detailText: root.homeWgDetail
|
|
||||||
installed: root.homeWgInstalled
|
|
||||||
missingText: "Not set up"
|
|
||||||
onToggle: root.toggleHomeWg()
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusLine { message: root.homeWgActionStatus }
|
|
||||||
|
|
||||||
// Imports (or replaces) the UniFi client .conf through a
|
|
||||||
// file chooser. Hidden while connected — replacing
|
|
||||||
// deletes the profile, which would drop the tunnel.
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
implicitHeight: importRow.implicitHeight + 8
|
|
||||||
visible: root.homeWgState === "disconnected"
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: importRow
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 34
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: 4
|
|
||||||
opacity: root.homeWgImporting ? 0.5 : 1
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: root.homeWgInstalled ? "sync" : "upload_file"
|
|
||||||
font.family: Appearance.iconFontFamilyRounded
|
|
||||||
font.variableAxes: Appearance.iconFontAxes
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: importMouse.containsMouse ? Colors.foreground : Colors.primary
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: root.homeWgImporting ? "Choosing file…"
|
|
||||||
: root.homeWgInstalled ? "Replace config" : "Add config"
|
|
||||||
font.family: Appearance.fontFamily
|
|
||||||
font.pixelSize: Appearance.fontSizeSmall
|
|
||||||
font.underline: importMouse.containsMouse
|
|
||||||
color: importMouse.containsMouse ? Colors.foreground : Colors.primary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: importMouse
|
|
||||||
anchors.fill: importRow
|
|
||||||
anchors.margins: -4
|
|
||||||
enabled: !root.homeWgImporting
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: root.importHomeWgConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|||||||
Reference in New Issue
Block a user