mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
chore: Tidy up superfluous whitespace (#503)
This commit is contained in:
22
CLAUDE.md
22
CLAUDE.md
@@ -191,9 +191,9 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
|
||||
property type value: defaultValue
|
||||
|
||||
|
||||
function performAction() { /* implementation */ }
|
||||
}
|
||||
```
|
||||
@@ -251,23 +251,23 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
// For regular components
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
||||
property type name: value
|
||||
|
||||
|
||||
signal customSignal(type param)
|
||||
|
||||
|
||||
onSignal: { /* handler */ }
|
||||
|
||||
|
||||
Component { /* children */ }
|
||||
}
|
||||
|
||||
|
||||
// For services (singletons)
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
|
||||
property bool featureAvailable: false
|
||||
property type currentValue: defaultValue
|
||||
|
||||
|
||||
function performAction(param) { /* implementation */ }
|
||||
}
|
||||
```
|
||||
@@ -305,7 +305,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
```qml
|
||||
// In services - detect capabilities
|
||||
property bool brightnessAvailable: false
|
||||
|
||||
|
||||
// In modules - adapt UI accordingly
|
||||
DankSlider {
|
||||
visible: DisplayService.brightnessAvailable
|
||||
@@ -335,7 +335,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
console.log("Info message") // General info
|
||||
console.warn("Warning message") // Warnings
|
||||
console.error("Error message") // Errors
|
||||
|
||||
|
||||
// Include context in service operations
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
|
||||
@@ -16,7 +16,7 @@ Singleton {
|
||||
return [fullUnderscore, fullHyphen, _lang].filter(c => c && c !== "en");
|
||||
}
|
||||
|
||||
|
||||
|
||||
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
|
||||
|
||||
property string currentLocale: "en"
|
||||
|
||||
@@ -1180,7 +1180,7 @@ Singleton {
|
||||
showWorkspaceIndex = enabled
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
|
||||
function setWorkspaceScrolling(enabled) {
|
||||
workspaceScrolling = enabled
|
||||
saveSettings()
|
||||
|
||||
@@ -61,7 +61,7 @@ Singleton {
|
||||
}
|
||||
readonly property string rawWallpaperPath: {
|
||||
if (typeof SessionData === "undefined") return ""
|
||||
|
||||
|
||||
if (SessionData.perMonitorWallpaper) {
|
||||
// Use first monitor's wallpaper for dynamic theming
|
||||
var screens = Quickshell.screens
|
||||
|
||||
@@ -84,7 +84,7 @@ Item {
|
||||
id: clipboardListView
|
||||
anchors.fill: parent
|
||||
model: filteredModel
|
||||
|
||||
|
||||
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0
|
||||
spacing: Theme.spacingXS
|
||||
interactive: true
|
||||
@@ -94,7 +94,7 @@ Item {
|
||||
boundsMovement: Flickable.FollowBoundsBehavior
|
||||
pressDelay: 0
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count) {
|
||||
return
|
||||
@@ -108,13 +108,13 @@ Item {
|
||||
contentY = itemBottom - height
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (clipboardContent.modal && clipboardContent.modal.keyboardNavigationActive && currentIndex >= 0) {
|
||||
ensureVisible(currentIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("No clipboard entries found")
|
||||
anchors.centerIn: parent
|
||||
@@ -122,11 +122,11 @@ Item {
|
||||
color: Theme.surfaceVariantText
|
||||
visible: filteredModel.count === 0
|
||||
}
|
||||
|
||||
|
||||
delegate: ClipboardEntry {
|
||||
required property int index
|
||||
required property var model
|
||||
|
||||
|
||||
width: clipboardListView.width
|
||||
height: ClipboardConstants.itemHeight
|
||||
entryData: model.entry
|
||||
|
||||
@@ -111,18 +111,18 @@ DankModal {
|
||||
if (!normalizedPath.startsWith("file://")) {
|
||||
normalizedPath = "file://" + filePath
|
||||
}
|
||||
|
||||
|
||||
// Check if file exists by looking through the folder model
|
||||
var exists = false
|
||||
var fileName = filePath.split('/').pop()
|
||||
|
||||
|
||||
for (var i = 0; i < folderModel.count; i++) {
|
||||
if (folderModel.get(i, "fileName") === fileName && !folderModel.get(i, "fileIsDir")) {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (exists) {
|
||||
pendingFilePath = normalizedPath
|
||||
showOverwriteConfirmation = true
|
||||
@@ -139,7 +139,7 @@ DankModal {
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath()
|
||||
}
|
||||
|
||||
|
||||
property var steamPaths: [
|
||||
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.steam/steam/steamapps/workshop/content/431960",
|
||||
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.local/share/Steam/steamapps/workshop/content/431960",
|
||||
@@ -147,17 +147,17 @@ DankModal {
|
||||
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/snap/steam/common/.local/share/Steam/steamapps/workshop/content/431960"
|
||||
]
|
||||
property int currentPathIndex: 0
|
||||
|
||||
|
||||
function discoverWallpaperEngine() {
|
||||
currentPathIndex = 0
|
||||
checkNextPath()
|
||||
}
|
||||
|
||||
|
||||
function checkNextPath() {
|
||||
if (currentPathIndex >= steamPaths.length) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const wePath = steamPaths[currentPathIndex]
|
||||
const cleanPath = wePath.replace(/^file:\/\//, '')
|
||||
weDiscoveryProcess.command = ["test", "-d", cleanPath]
|
||||
@@ -451,13 +451,13 @@ DankModal {
|
||||
executeKeyboardSelection(targetIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Process {
|
||||
id: weDiscoveryProcess
|
||||
|
||||
|
||||
property string wePath: ""
|
||||
running: false
|
||||
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode === 0) {
|
||||
fileBrowserModal.weAvailable = true
|
||||
@@ -532,7 +532,7 @@ DankModal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankActionButton {
|
||||
circular: false
|
||||
iconName: "info"
|
||||
@@ -875,26 +875,26 @@ DankModal {
|
||||
id: overwriteDialog
|
||||
anchors.fill: parent
|
||||
visible: showOverwriteConfirmation
|
||||
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
showOverwriteConfirmation = false
|
||||
pendingFilePath = ""
|
||||
}
|
||||
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
showOverwriteConfirmation = false
|
||||
fileSelected(pendingFilePath)
|
||||
pendingFilePath = ""
|
||||
Qt.callLater(() => fileBrowserModal.close())
|
||||
}
|
||||
|
||||
|
||||
focus: showOverwriteConfirmation
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Theme.shadowStrong
|
||||
opacity: 0.8
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
@@ -903,7 +903,7 @@ DankModal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledRect {
|
||||
anchors.centerIn: parent
|
||||
width: 400
|
||||
@@ -912,12 +912,12 @@ DankModal {
|
||||
radius: Theme.cornerRadius
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingL * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("File Already Exists")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -925,7 +925,7 @@ DankModal {
|
||||
color: Theme.surfaceText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("A file with this name already exists. Do you want to overwrite it?")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -934,11 +934,11 @@ DankModal {
|
||||
wrapMode: Text.WordWrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 80
|
||||
height: 36
|
||||
@@ -946,7 +946,7 @@ DankModal {
|
||||
color: cancelArea.containsMouse ? Theme.surfaceVariantHover : Theme.surfaceVariant
|
||||
border.color: Theme.outline
|
||||
border.width: 1
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("Cancel")
|
||||
@@ -954,7 +954,7 @@ DankModal {
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: cancelArea
|
||||
anchors.fill: parent
|
||||
@@ -966,13 +966,13 @@ DankModal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 90
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: overwriteArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("Overwrite")
|
||||
@@ -980,7 +980,7 @@ DankModal {
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: overwriteArea
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -20,7 +20,7 @@ DankModal {
|
||||
if (modalKeyboardController && notificationListRef) {
|
||||
modalKeyboardController.listView = notificationListRef
|
||||
modalKeyboardController.rebuildFlatNavigation()
|
||||
|
||||
|
||||
Qt.callLater(() => {
|
||||
modalKeyboardController.keyboardNavigationActive = true
|
||||
modalKeyboardController.selectedFlatIndex = 0
|
||||
|
||||
@@ -285,12 +285,12 @@ Item {
|
||||
}
|
||||
|
||||
const triggers = PluginService.getAllPluginTriggers()
|
||||
|
||||
|
||||
for (const trigger in triggers) {
|
||||
if (query.startsWith(trigger)) {
|
||||
const pluginId = triggers[trigger]
|
||||
const plugin = PluginService.getLauncherPlugin(pluginId)
|
||||
|
||||
|
||||
if (plugin) {
|
||||
const remainingQuery = query.substring(trigger.length).trim()
|
||||
const result = {
|
||||
@@ -304,7 +304,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return { triggered: false, pluginCategory: "", query: "" }
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Rectangle {
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
anchors.left: parent.left
|
||||
@@ -27,7 +27,7 @@ Rectangle {
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingS
|
||||
height: 40
|
||||
|
||||
|
||||
StyledText {
|
||||
id: headerText
|
||||
text: I18n.tr("Input Devices")
|
||||
@@ -37,7 +37,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
id: volumeSlider
|
||||
anchors.left: parent.left
|
||||
@@ -105,7 +105,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankFlickable {
|
||||
id: audioContent
|
||||
anchors.top: hasInputVolumeSliderInCC ? headerRow.bottom : volumeSlider.bottom
|
||||
@@ -116,34 +116,34 @@ Rectangle {
|
||||
anchors.topMargin: hasInputVolumeSliderInCC ? Theme.spacingM : Theme.spacingS
|
||||
contentHeight: audioColumn.height
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: audioColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
Repeater {
|
||||
model: Pipewire.nodes.values.filter(node => {
|
||||
return node.audio && !node.isSink && !node.isStream
|
||||
})
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
||||
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
if (modelData.name.includes("bluez"))
|
||||
@@ -157,11 +157,11 @@ Rectangle {
|
||||
color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
|
||||
|
||||
|
||||
StyledText {
|
||||
text: AudioService.displayName(modelData)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -171,7 +171,7 @@ Rectangle {
|
||||
width: parent.width
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData === AudioService.source ? "Active" : "Available"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -182,7 +182,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: deviceMouseArea
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -17,7 +17,7 @@ Rectangle {
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
anchors.left: parent.left
|
||||
@@ -27,7 +27,7 @@ Rectangle {
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingS
|
||||
height: 40
|
||||
|
||||
|
||||
StyledText {
|
||||
id: headerText
|
||||
text: I18n.tr("Audio Devices")
|
||||
@@ -121,34 +121,34 @@ Rectangle {
|
||||
anchors.topMargin: volumeSlider.visible ? Theme.spacingS : Theme.spacingM
|
||||
contentHeight: audioColumn.height
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: audioColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
Repeater {
|
||||
model: Pipewire.nodes.values.filter(node => {
|
||||
return node.audio && node.isSink && !node.isStream
|
||||
})
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
||||
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
if (modelData.name.includes("bluez"))
|
||||
@@ -164,11 +164,11 @@ Rectangle {
|
||||
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
|
||||
|
||||
|
||||
StyledText {
|
||||
text: AudioService.displayName(modelData)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -178,7 +178,7 @@ Rectangle {
|
||||
width: parent.width
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData === AudioService.sink ? "Active" : "Available"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -189,7 +189,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: deviceMouseArea
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -83,12 +83,12 @@ Item {
|
||||
hoverEnabled: true
|
||||
preventStealing: true
|
||||
propagateComposedEvents: false
|
||||
|
||||
|
||||
onClicked: root.hide()
|
||||
onWheel: (wheel) => { wheel.accepted = true }
|
||||
onPositionChanged: (mouse) => { mouse.accepted = true }
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: modalBackground
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -12,11 +12,11 @@ Rectangle {
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 0
|
||||
|
||||
|
||||
property var bluetoothCodecModalRef: null
|
||||
|
||||
|
||||
signal showCodecSelector(var device)
|
||||
|
||||
|
||||
function updateDeviceCodecDisplay(deviceAddress, codecName) {
|
||||
for (let i = 0; i < pairedRepeater.count; i++) {
|
||||
let item = pairedRepeater.itemAt(i)
|
||||
@@ -26,7 +26,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
anchors.left: parent.left
|
||||
@@ -36,7 +36,7 @@ Rectangle {
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingS
|
||||
height: 40
|
||||
|
||||
|
||||
StyledText {
|
||||
id: headerText
|
||||
text: I18n.tr("Bluetooth Settings")
|
||||
@@ -45,12 +45,12 @@ Rectangle {
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
width: Math.max(0, parent.width - headerText.implicitWidth - scanButton.width - Theme.spacingM)
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: scanButton
|
||||
width: 100
|
||||
@@ -64,18 +64,18 @@ Rectangle {
|
||||
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 0
|
||||
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching"
|
||||
size: 18
|
||||
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: BluetoothService.adapter && BluetoothService.adapter.discovering ? "Scanning" : "Scan"
|
||||
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceVariantText
|
||||
@@ -84,7 +84,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: scanMouseArea
|
||||
anchors.fill: parent
|
||||
@@ -98,7 +98,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankFlickable {
|
||||
id: bluetoothContent
|
||||
anchors.top: headerRow.bottom
|
||||
@@ -110,19 +110,19 @@ Rectangle {
|
||||
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
||||
contentHeight: bluetoothColumn.height
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: bluetoothColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
|
||||
|
||||
Repeater {
|
||||
id: pairedRepeater
|
||||
model: {
|
||||
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
|
||||
return []
|
||||
|
||||
|
||||
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
||||
devices.sort((a, b) => {
|
||||
if (a.connected && !b.connected) return -1
|
||||
@@ -131,17 +131,17 @@ Rectangle {
|
||||
})
|
||||
return devices
|
||||
}
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
property string currentCodec: BluetoothService.deviceCodecs[modelData.address] || ""
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
if (modelData.connected && BluetoothService.isAudioDevice(modelData)) {
|
||||
BluetoothService.refreshDeviceCodec(modelData)
|
||||
@@ -162,13 +162,13 @@ Rectangle {
|
||||
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
}
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: BluetoothService.getDeviceIcon(modelData)
|
||||
size: Theme.iconSize - 4
|
||||
@@ -181,11 +181,11 @@ Rectangle {
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.name || modelData.deviceName || "Unknown Device"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -194,10 +194,10 @@ Rectangle {
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (modelData.state === BluetoothDeviceState.Connecting)
|
||||
@@ -218,12 +218,12 @@ Rectangle {
|
||||
return Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (modelData.batteryAvailable && modelData.battery > 0)
|
||||
return "• " + Math.round(modelData.battery * 100) + "%"
|
||||
|
||||
|
||||
var btBattery = BatteryService.bluetoothDevices.find(dev => {
|
||||
return dev.name === (modelData.name || modelData.deviceName) ||
|
||||
dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) ||
|
||||
@@ -235,7 +235,7 @@ Rectangle {
|
||||
color: Theme.surfaceVariantText
|
||||
visible: text.length > 0
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.signalStrength !== undefined && modelData.signalStrength > 0 ? "• " + modelData.signalStrength + "%" : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -245,7 +245,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankActionButton {
|
||||
id: pairedOptionsButton
|
||||
anchors.right: parent.right
|
||||
@@ -262,7 +262,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: deviceMouseArea
|
||||
anchors.fill: parent
|
||||
@@ -279,26 +279,26 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
visible: pairedRepeater.count > 0 && availableRepeater.count > 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 80
|
||||
visible: BluetoothService.adapter && BluetoothService.adapter.discovering && availableRepeater.count === 0
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "sync"
|
||||
size: 24
|
||||
color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.4)
|
||||
|
||||
|
||||
RotationAnimation on rotation {
|
||||
running: parent.visible && BluetoothService.adapter && BluetoothService.adapter.discovering && availableRepeater.count === 0
|
||||
loops: Animation.Infinite
|
||||
@@ -308,27 +308,27 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Repeater {
|
||||
id: availableRepeater
|
||||
model: {
|
||||
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
|
||||
return []
|
||||
|
||||
|
||||
var filtered = Bluetooth.devices.values.filter(dev => {
|
||||
return dev && !dev.paired && !dev.pairing && !dev.blocked &&
|
||||
(dev.signalStrength === undefined || dev.signalStrength > 0)
|
||||
})
|
||||
return BluetoothService.sortDevices(filtered)
|
||||
}
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
property bool canConnect: BluetoothService.canConnect(modelData)
|
||||
property bool isBusy: BluetoothService.isDeviceBusy(modelData)
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
@@ -336,24 +336,24 @@ Rectangle {
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 0
|
||||
opacity: canConnect ? 1 : 0.6
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: BluetoothService.getDeviceIcon(modelData)
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.name || modelData.deviceName || "Unknown Device"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -361,10 +361,10 @@ Rectangle {
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (modelData.pairing) return "Pairing..."
|
||||
@@ -374,7 +374,7 @@ Rectangle {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.signalStrength !== undefined && modelData.signalStrength > 0 ? "• " + modelData.signalStrength + "%" : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -384,7 +384,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
@@ -398,7 +398,7 @@ Rectangle {
|
||||
color: canConnect ? Theme.primary : Theme.surfaceVariantText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: availableMouseArea
|
||||
anchors.fill: parent
|
||||
@@ -411,15 +411,15 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 60
|
||||
visible: !BluetoothService.adapter
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("No Bluetooth adapter found")
|
||||
@@ -429,25 +429,25 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Menu {
|
||||
id: bluetoothContextMenu
|
||||
width: 150
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
|
||||
property var currentDevice: null
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 0
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: bluetoothContextMenu.currentDevice && bluetoothContextMenu.currentDevice.connected ? "Disconnect" : "Connect"
|
||||
height: 32
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -455,12 +455,12 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
if (bluetoothContextMenu.currentDevice) {
|
||||
if (bluetoothContextMenu.currentDevice.connected) {
|
||||
@@ -471,12 +471,12 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: I18n.tr("Audio Codec")
|
||||
height: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected ? 32 : 0
|
||||
visible: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -484,23 +484,23 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
if (bluetoothContextMenu.currentDevice) {
|
||||
showCodecSelector(bluetoothContextMenu.currentDevice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: I18n.tr("Forget Device")
|
||||
height: 32
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -508,12 +508,12 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
if (bluetoothContextMenu.currentDevice) {
|
||||
bluetoothContextMenu.currentDevice.forget()
|
||||
@@ -521,5 +521,5 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ Rectangle {
|
||||
Component.onDestruction: {
|
||||
NetworkService.removeRef()
|
||||
}
|
||||
|
||||
|
||||
property int currentPreferenceIndex: {
|
||||
if (DMSService.apiVersion < 5) {
|
||||
return 1
|
||||
@@ -88,7 +88,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: wifiToggleContent
|
||||
anchors.top: headerRow.bottom
|
||||
@@ -127,7 +127,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: wifiOffContent
|
||||
anchors.top: headerRow.bottom
|
||||
@@ -137,19 +137,19 @@ Rectangle {
|
||||
anchors.topMargin: Theme.spacingM
|
||||
visible: currentPreferenceIndex === 1 && !NetworkService.wifiEnabled && !NetworkService.wifiToggling
|
||||
height: visible ? 120 : 0
|
||||
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingL
|
||||
width: parent.width
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
name: "wifi_off"
|
||||
size: 48
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: I18n.tr("WiFi is off")
|
||||
@@ -158,7 +158,7 @@ Rectangle {
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 120
|
||||
@@ -167,7 +167,7 @@ Rectangle {
|
||||
color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
|
||||
border.width: 0
|
||||
border.color: Theme.primary
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("Enable WiFi")
|
||||
@@ -175,7 +175,7 @@ Rectangle {
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: enableWifiButton
|
||||
anchors.fill: parent
|
||||
@@ -257,7 +257,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankActionButton {
|
||||
id: wiredOptionsButton
|
||||
anchors.right: parent.right
|
||||
@@ -295,7 +295,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Menu {
|
||||
id: wiredNetworkContextMenu
|
||||
width: 150
|
||||
@@ -376,7 +376,7 @@ Rectangle {
|
||||
id: wifiColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 200
|
||||
@@ -397,7 +397,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Repeater {
|
||||
model: sortedNetworks
|
||||
|
||||
@@ -415,20 +415,20 @@ Rectangle {
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
||||
border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 0
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
let strength = modelData.signal || 0
|
||||
@@ -440,11 +440,11 @@ Rectangle {
|
||||
color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.ssid || "Unknown Network"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -462,14 +462,14 @@ Rectangle {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData.saved ? "Saved" : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.primary
|
||||
visible: text.length > 0
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: (modelData.saved ? "• " : "") + modelData.signal + "%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -478,7 +478,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankActionButton {
|
||||
id: optionsButton
|
||||
anchors.right: parent.right
|
||||
@@ -499,7 +499,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: networkMouseArea
|
||||
anchors.fill: parent
|
||||
@@ -517,34 +517,34 @@ Rectangle {
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Menu {
|
||||
id: networkContextMenu
|
||||
width: 150
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
|
||||
property string currentSSID: ""
|
||||
property bool currentSecured: false
|
||||
property bool currentConnected: false
|
||||
property bool currentSaved: false
|
||||
property int currentSignal: 0
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 0
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: networkContextMenu.currentConnected ? "Disconnect" : "Connect"
|
||||
height: 32
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -552,12 +552,12 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
if (networkContextMenu.currentConnected) {
|
||||
NetworkService.disconnectWifi()
|
||||
@@ -570,11 +570,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: I18n.tr("Network Info")
|
||||
height: 32
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -582,23 +582,23 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID)
|
||||
networkInfoModal.showNetworkInfo(networkContextMenu.currentSSID, networkData)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MenuItem {
|
||||
text: I18n.tr("Forget Network")
|
||||
height: networkContextMenu.currentSaved || networkContextMenu.currentConnected ? 32 : 0
|
||||
visible: networkContextMenu.currentSaved || networkContextMenu.currentConnected
|
||||
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -606,18 +606,18 @@ Rectangle {
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
|
||||
onTriggered: {
|
||||
NetworkService.forgetWifiNetwork(networkContextMenu.currentSSID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WifiPasswordModal {
|
||||
id: wifiPasswordModal
|
||||
}
|
||||
@@ -625,7 +625,7 @@ Rectangle {
|
||||
NetworkInfoModal {
|
||||
id: networkInfoModal
|
||||
}
|
||||
|
||||
|
||||
NetworkWiredInfoModal {
|
||||
id: networkWiredInfoModal
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ Rectangle {
|
||||
property real maximumValue: 1.0
|
||||
property real minimumValue: 0.0
|
||||
property bool enabled: true
|
||||
|
||||
|
||||
signal sliderValueChanged(real value)
|
||||
|
||||
width: parent ? parent.width : 200
|
||||
|
||||
@@ -38,7 +38,7 @@ Item {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
root.clicked();
|
||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
||||
const globalPos = mapToGlobal(0, 0);
|
||||
|
||||
@@ -82,20 +82,20 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
|
||||
|
||||
property real scrollAccumulator: 0
|
||||
property real touchpadThreshold: 500
|
||||
|
||||
|
||||
onWheel: (wheel) => {
|
||||
const deltaY = wheel.angleDelta.y;
|
||||
const isMouseWheel = Math.abs(deltaY) >= 120
|
||||
&& (Math.abs(deltaY) % 120) === 0;
|
||||
|
||||
|
||||
const windows = root.sortedToplevels;
|
||||
if (windows.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (isMouseWheel) {
|
||||
// Direct mouse wheel action
|
||||
let currentIndex = -1;
|
||||
@@ -128,7 +128,7 @@ Rectangle {
|
||||
} else {
|
||||
// Touchpad - accumulate small deltas
|
||||
scrollAccumulator += deltaY;
|
||||
|
||||
|
||||
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
|
||||
let currentIndex = -1;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
@@ -157,11 +157,11 @@ Rectangle {
|
||||
if (nextWindow) {
|
||||
nextWindow.activate();
|
||||
}
|
||||
|
||||
|
||||
scrollAccumulator = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wheel.accepted = true;
|
||||
}
|
||||
}
|
||||
@@ -640,51 +640,51 @@ Rectangle {
|
||||
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: windowContextMenuLoader
|
||||
active: false
|
||||
sourceComponent: PanelWindow {
|
||||
id: contextMenuWindow
|
||||
|
||||
|
||||
property var currentWindow: null
|
||||
property bool isVisible: false
|
||||
property point anchorPos: Qt.point(0, 0)
|
||||
|
||||
|
||||
function showAt(x, y) {
|
||||
screen = root.parentScreen;
|
||||
anchorPos = Qt.point(x, y);
|
||||
isVisible = true;
|
||||
visible = true;
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
isVisible = false;
|
||||
visible = false;
|
||||
windowContextMenuLoader.active = false;
|
||||
}
|
||||
|
||||
|
||||
implicitWidth: 100
|
||||
implicitHeight: 40
|
||||
visible: false
|
||||
color: "transparent"
|
||||
|
||||
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: contextMenuWindow.close();
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
x: {
|
||||
const left = 10;
|
||||
@@ -699,13 +699,13 @@ Rectangle {
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
color: closeMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("Close")
|
||||
@@ -713,7 +713,7 @@ Rectangle {
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Normal
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: closeMouseArea
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -290,7 +290,7 @@ Rectangle {
|
||||
nextWindow.activate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
scrollAccumulator += deltaY
|
||||
|
||||
@@ -331,7 +331,7 @@ Rectangle {
|
||||
nextWindow.activate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
scrollAccumulator = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,11 +134,11 @@ DankPopout {
|
||||
{ icon: "dashboard", text: I18n.tr("Overview") },
|
||||
{ icon: "music_note", text: I18n.tr("Media") }
|
||||
]
|
||||
|
||||
|
||||
if (SettingsData.weatherEnabled) {
|
||||
tabs.push({ icon: "wb_sunny", text: I18n.tr("Weather") })
|
||||
}
|
||||
|
||||
|
||||
tabs.push({ icon: "settings", text: I18n.tr("Settings"), isAction: true })
|
||||
return tabs
|
||||
}
|
||||
|
||||
@@ -128,9 +128,9 @@ Item {
|
||||
|
||||
function getAudioDeviceIcon(device) {
|
||||
if (!device || !device.name) return "speaker"
|
||||
|
||||
|
||||
const name = device.name.toLowerCase()
|
||||
|
||||
|
||||
if (name.includes("bluez") || name.includes("bluetooth"))
|
||||
return "headset"
|
||||
if (name.includes("hdmi"))
|
||||
@@ -139,10 +139,10 @@ Item {
|
||||
return "headset"
|
||||
if (name.includes("analog") || name.includes("built-in"))
|
||||
return "speaker"
|
||||
|
||||
|
||||
return "speaker"
|
||||
}
|
||||
|
||||
|
||||
function getVolumeIcon(sink) {
|
||||
if (!sink || !sink.audio) return "volume_off"
|
||||
|
||||
@@ -262,8 +262,8 @@ Item {
|
||||
maybeFinishSwitch()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
property bool isSeeking: false
|
||||
|
||||
@@ -325,7 +325,7 @@ Item {
|
||||
return mouse.x < item.x || mouse.x > item.x + item.width ||
|
||||
mouse.y < item.y || mouse.y > item.y + item.height
|
||||
}
|
||||
|
||||
|
||||
if (playerSelectorButton.playersExpanded && clickOutside(playerSelectorDropdown)) {
|
||||
playerSelectorButton.playersExpanded = false
|
||||
}
|
||||
@@ -400,11 +400,11 @@ Item {
|
||||
easing.bezierCurve: Anims.standard
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Audio Output Devices (") + audioDevicesDropdown.availableDevices.length + ")"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -414,49 +414,49 @@ Item {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
bottomPadding: Theme.spacingM
|
||||
}
|
||||
|
||||
|
||||
DankFlickable {
|
||||
width: parent.width
|
||||
height: parent.height - 40
|
||||
contentHeight: deviceColumn.height
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: deviceColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
Repeater {
|
||||
model: audioDevicesDropdown.availableDevices
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: 48
|
||||
radius: Theme.cornerRadius
|
||||
color: deviceMouseAreaLeft.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.surfaceContainerHigh
|
||||
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: modelData === AudioService.sink ? 2 : 1
|
||||
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingM
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: getAudioDeviceIcon(modelData)
|
||||
size: 20
|
||||
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width - 20 - Theme.spacingM * 2
|
||||
|
||||
|
||||
StyledText {
|
||||
text: AudioService.displayName(modelData)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -466,7 +466,7 @@ Item {
|
||||
width: parent.width
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: modelData === AudioService.sink ? "Active" : "Available"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -477,7 +477,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: deviceMouseAreaLeft
|
||||
anchors.fill: parent
|
||||
@@ -490,7 +490,7 @@ Item {
|
||||
audioDevicesButton.devicesExpanded = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Behavior on border.color { ColorAnimation { duration: Anims.durShort } }
|
||||
}
|
||||
}
|
||||
@@ -793,7 +793,7 @@ Item {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -812,7 +812,7 @@ Item {
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 50
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingM
|
||||
|
||||
@@ -92,12 +92,12 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
visible: showEventDetails
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: 32
|
||||
height: 32
|
||||
@@ -122,7 +122,7 @@ Rectangle {
|
||||
onClicked: root.showEventDetails = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -149,7 +149,7 @@ Rectangle {
|
||||
width: parent.width
|
||||
height: 28
|
||||
visible: !showEventDetails
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
@@ -215,7 +215,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 18
|
||||
@@ -248,14 +248,14 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Grid {
|
||||
id: calendarGrid
|
||||
visible: !showEventDetails
|
||||
|
||||
|
||||
property date displayDate: systemClock.date
|
||||
property date selectedDate: systemClock.date
|
||||
|
||||
|
||||
readonly property date firstDay: {
|
||||
const firstOfMonth = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
|
||||
return startOfWeek(firstOfMonth)
|
||||
@@ -341,7 +341,7 @@ Rectangle {
|
||||
visible: showEventDetails
|
||||
clip: true
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
width: parent ? parent.width : 0
|
||||
height: eventContent.implicitHeight + Theme.spacingS
|
||||
@@ -377,7 +377,7 @@ Rectangle {
|
||||
|
||||
Column {
|
||||
id: eventContent
|
||||
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -419,7 +419,7 @@ Rectangle {
|
||||
|
||||
MouseArea {
|
||||
id: eventMouseArea
|
||||
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: modelData.url ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
|
||||
@@ -4,9 +4,9 @@ import qs.Common
|
||||
|
||||
Rectangle {
|
||||
id: card
|
||||
|
||||
|
||||
property int pad: Theme.spacingM
|
||||
|
||||
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
|
||||
@@ -35,7 +35,7 @@ Card {
|
||||
width: 28
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (SettingsData.use24HourClock) {
|
||||
@@ -53,7 +53,7 @@ Card {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
spacing: 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -66,7 +66,7 @@ Card {
|
||||
width: 28
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
|
||||
font.pixelSize: 48
|
||||
@@ -102,7 +102,7 @@ Card {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: systemClock?.date?.toLocaleDateString(Qt.locale(), "MMM dd")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
|
||||
@@ -92,7 +92,7 @@ Card {
|
||||
}
|
||||
// Just using truncated is always true initially idk
|
||||
property bool shouldUseShort: longTextWidth > availableWidth
|
||||
|
||||
|
||||
text: shouldUseShort ? UserInfoService.shortUptime : UserInfoService.uptime || "up 1h 23m"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||
|
||||
@@ -47,18 +47,18 @@ Card {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingL
|
||||
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||
size: 48
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
@@ -71,7 +71,7 @@ Card {
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Light
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: WeatherService.getWeatherCondition(WeatherService.weather.wCode)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
|
||||
@@ -132,7 +132,7 @@ Item {
|
||||
anchors.left: tempText.right
|
||||
anchors.leftMargin: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
@@ -540,7 +540,7 @@ Item {
|
||||
width: (parent.width - Theme.spacingXS * 6) / 7
|
||||
height: parent.height
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
|
||||
property var dayDate: {
|
||||
const date = new Date()
|
||||
date.setDate(date.getDate() + index)
|
||||
|
||||
@@ -75,14 +75,14 @@ Column {
|
||||
|
||||
property string lastTextForLineModel: ""
|
||||
property var lineModel: []
|
||||
|
||||
|
||||
function updateLineModel() {
|
||||
if (!SettingsData.notepadShowLineNumbers) {
|
||||
lineModel = []
|
||||
lastTextForLineModel = ""
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (textArea.text !== lastTextForLineModel || lineModel.length === 0) {
|
||||
lastTextForLineModel = textArea.text
|
||||
lineModel = textArea.text.split('\n')
|
||||
@@ -129,10 +129,10 @@ Column {
|
||||
function highlightCurrentMatch() {
|
||||
if (currentMatchIndex >= 0 && currentMatchIndex < searchMatches.length) {
|
||||
const match = searchMatches[currentMatchIndex]
|
||||
|
||||
|
||||
textArea.cursorPosition = match.start
|
||||
textArea.moveCursorSelection(match.end, TextEdit.SelectCharacters)
|
||||
|
||||
|
||||
const flickable = textArea.parent
|
||||
if (flickable && flickable.contentY !== undefined) {
|
||||
const lineHeight = textArea.font.pixelSize * 1.5
|
||||
@@ -219,11 +219,11 @@ Column {
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
selectByMouse: true
|
||||
clip: true
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
text = root.searchQuery
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onSearchQueryChanged() {
|
||||
@@ -232,7 +232,7 @@ Column {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onTextChanged: {
|
||||
if (root.searchQuery !== text) {
|
||||
root.searchQuery = text
|
||||
@@ -260,7 +260,7 @@ Column {
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Placeholder text
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -366,7 +366,7 @@ Item {
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
|
||||
StyledText {
|
||||
text: `<a href="https://github.com/YaLTeR/niri" style="text-decoration:none; color:${Theme.primary};">niri</a>`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -383,14 +383,14 @@ Item {
|
||||
propagateComposedEvents: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "&"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: `<a href="https://github.com/hyprwm/Hyprland" style="text-decoration:none; color:${Theme.primary};">hyprland</a>`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -418,7 +418,7 @@ Item {
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
|
||||
StyledText {
|
||||
text: `<a href="https://github.com/AvengeMedia/DankMaterialShell" style="text-decoration:none; color:${Theme.primary};">DankMaterialShell</a>`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -435,7 +435,7 @@ Item {
|
||||
propagateComposedEvents: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("- Support Us With a Star ⭐")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -453,7 +453,7 @@ Item {
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
|
||||
StyledText {
|
||||
text: `<a href="https://github.com/AvengeMedia/dgop" style="text-decoration:none; color:${Theme.primary};">dgop</a>`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -470,7 +470,7 @@ Item {
|
||||
propagateComposedEvents: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("- Stateless System Monitoring")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -488,7 +488,7 @@ Item {
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
|
||||
StyledText {
|
||||
text: `<a href="https://danklinux.com" style="text-decoration:none; color:${Theme.primary};">danklinux.com</a>`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
|
||||
@@ -371,7 +371,7 @@ Item {
|
||||
widgets = SettingsData.dankBarCenterWidgets.slice()
|
||||
else if (sectionId === "right")
|
||||
widgets = SettingsData.dankBarRightWidgets.slice()
|
||||
|
||||
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
var widget = widgets[widgetIndex]
|
||||
var widgetId = typeof widget === "string" ? widget : widget.id
|
||||
@@ -401,7 +401,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sectionId === "left")
|
||||
SettingsData.setDankBarLeftWidgets(widgets)
|
||||
else if (sectionId === "center")
|
||||
|
||||
@@ -734,11 +734,11 @@ Column {
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
|
||||
onOpened: {
|
||||
console.log("Control Center context menu opened")
|
||||
}
|
||||
|
||||
|
||||
onClosed: {
|
||||
console.log("Control Center context menu closed")
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ Item {
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("LauncherExample: Plugin loaded")
|
||||
|
||||
|
||||
// Load custom trigger from settings
|
||||
if (pluginService) {
|
||||
trigger = pluginService.loadPluginData("launcherExample", "trigger", "#")
|
||||
@@ -119,7 +119,7 @@ Item {
|
||||
function runScript(command) {
|
||||
console.log("LauncherExample: Would run script:", command)
|
||||
showToast("Script executed: " + command)
|
||||
|
||||
|
||||
// In a real plugin, you might create a Process component here
|
||||
// For demo purposes, we just show what would happen
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Singleton {
|
||||
id: root
|
||||
|
||||
property var applications: DesktopEntries.applications.values.filter(app => !app.noDisplay && !app.runInTerminal)
|
||||
|
||||
|
||||
|
||||
|
||||
function searchApplications(query) {
|
||||
@@ -266,7 +266,7 @@ Singleton {
|
||||
|
||||
function getPluginCategoryIcon(category) {
|
||||
if (typeof PluginService === "undefined") return null
|
||||
|
||||
|
||||
const launchers = PluginService.getLauncherPlugins()
|
||||
for (const pluginId in launchers) {
|
||||
const plugin = launchers[pluginId]
|
||||
@@ -296,7 +296,7 @@ Singleton {
|
||||
|
||||
function getPluginItems(category, query) {
|
||||
if (typeof PluginService === "undefined") return []
|
||||
|
||||
|
||||
const launchers = PluginService.getLauncherPlugins()
|
||||
for (const pluginId in launchers) {
|
||||
const plugin = launchers[pluginId]
|
||||
@@ -338,42 +338,42 @@ Singleton {
|
||||
|
||||
function executePluginItem(item, pluginId) {
|
||||
if (typeof PluginService === "undefined") return false
|
||||
|
||||
|
||||
const component = PluginService.pluginLauncherComponents[pluginId]
|
||||
if (!component) return false
|
||||
|
||||
|
||||
try {
|
||||
const instance = component.createObject(root, {
|
||||
"pluginService": PluginService
|
||||
})
|
||||
|
||||
|
||||
if (instance && typeof instance.executeItem === "function") {
|
||||
instance.executeItem(item)
|
||||
instance.destroy()
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
if (instance) {
|
||||
instance.destroy()
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("AppSearchService: Error executing item from plugin", pluginId, ":", e)
|
||||
}
|
||||
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function searchPluginItems(query) {
|
||||
if (typeof PluginService === "undefined") return []
|
||||
|
||||
|
||||
let allItems = []
|
||||
const launchers = PluginService.getLauncherPlugins()
|
||||
|
||||
|
||||
for (const pluginId in launchers) {
|
||||
const items = getPluginItemsForPlugin(pluginId, query)
|
||||
allItems = allItems.concat(items)
|
||||
}
|
||||
|
||||
|
||||
return allItems
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ Singleton {
|
||||
property string ethernetConnectionUuid: ""
|
||||
|
||||
property var wiredConnections: []
|
||||
|
||||
|
||||
property string wifiIP: ""
|
||||
property string wifiInterface: ""
|
||||
property bool wifiConnected: false
|
||||
@@ -75,7 +75,7 @@ Singleton {
|
||||
property string networkInfoSSID: ""
|
||||
property string networkInfoDetails: ""
|
||||
property bool networkInfoLoading: false
|
||||
|
||||
|
||||
property string networkWiredInfoUUID: ""
|
||||
property string networkWiredInfoDetails: ""
|
||||
property bool networkWiredInfoLoading: false
|
||||
@@ -158,12 +158,12 @@ Singleton {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (line.includes("StateChanged") ||
|
||||
line.includes("PrimaryConnectionChanged") ||
|
||||
line.includes("WirelessEnabled") ||
|
||||
(line.includes("ActiveConnection") && line.includes("State"))) {
|
||||
|
||||
|
||||
if (now - nmStateMonitor.lastRefreshTime > nmStateMonitor.minRefreshInterval) {
|
||||
nmStateMonitor.lastRefreshTime = now
|
||||
refreshNetworkState()
|
||||
|
||||
@@ -71,7 +71,7 @@ Singleton {
|
||||
property string networkInfoSSID: ""
|
||||
property string networkInfoDetails: ""
|
||||
property bool networkInfoLoading: false
|
||||
|
||||
|
||||
property string networkWiredInfoUUID: ""
|
||||
property string networkWiredInfoDetails: ""
|
||||
property bool networkWiredInfoLoading: false
|
||||
@@ -227,7 +227,7 @@ Singleton {
|
||||
|
||||
connectionChanged()
|
||||
}
|
||||
|
||||
|
||||
function connectToSpecificWiredConfig(uuid) {
|
||||
if (!networkAvailable || isConnecting) return
|
||||
|
||||
@@ -446,7 +446,7 @@ Singleton {
|
||||
autoScan = false
|
||||
autoRefreshEnabled = false
|
||||
}
|
||||
|
||||
|
||||
function fetchWiredNetworkInfo(uuid) {
|
||||
if (!networkAvailable) return
|
||||
|
||||
@@ -475,18 +475,18 @@ Singleton {
|
||||
details += "Driver: " + info.driver + "\\n"
|
||||
details += "MAC Addr: " + info.hwAddr + "\\n"
|
||||
details += "Speed: " + info.speed + " Mb/s\\n\\n"
|
||||
|
||||
|
||||
details += "IPv4 informations:\\n"
|
||||
|
||||
|
||||
for (const ip4 of info.IPv4s.ips) {
|
||||
details += " IPv4 address: " + ip4 + "\\n"
|
||||
}
|
||||
details += " Gateway: " + info.IPv4s.gateway + "\\n"
|
||||
details += " DNS: " + info.IPv4s.dns + "\\n"
|
||||
|
||||
|
||||
if (info.IPv6s.ips) {
|
||||
details += "\\nIPv6 informations:\\n"
|
||||
|
||||
|
||||
for (const ip6 of info.IPv6s.ips) {
|
||||
details += " IPv6 address: " + ip6 + "\\n"
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ Singleton {
|
||||
property string networkInfoSSID: activeService?.networkInfoSSID ?? ""
|
||||
property string networkInfoDetails: activeService?.networkInfoDetails ?? ""
|
||||
property bool networkInfoLoading: activeService?.networkInfoLoading ?? false
|
||||
|
||||
|
||||
property string networkWiredInfoUUID: activeService?.networkWiredInfoUUID ?? ""
|
||||
property string networkWiredInfoDetails: activeService?.networkWiredInfoDetails ?? ""
|
||||
property bool networkWiredInfoLoading: activeService?.networkWiredInfoLoading ?? false
|
||||
@@ -252,7 +252,7 @@ Singleton {
|
||||
activeService.refreshNetworkState()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function connectToSpecificWiredConfig(uuid) {
|
||||
if (activeService && activeService.connectToSpecificWiredConfig) {
|
||||
activeService.connectToSpecificWiredConfig(uuid)
|
||||
|
||||
@@ -538,7 +538,7 @@ Singleton {
|
||||
// Launcher plugin helper functions
|
||||
function getLauncherPlugins() {
|
||||
const launchers = {}
|
||||
|
||||
|
||||
// Check plugins that have launcher components
|
||||
for (const pluginId in pluginLauncherComponents) {
|
||||
const plugin = availablePlugins[pluginId]
|
||||
|
||||
@@ -302,7 +302,7 @@ Singleton {
|
||||
|
||||
function cyclePrevForMonitor(screenName) {
|
||||
if (!screenName) return
|
||||
|
||||
|
||||
var currentWallpaper = SessionData.getMonitorWallpaper(screenName)
|
||||
if (currentWallpaper) {
|
||||
cycleToPrevWallpaper(screenName, currentWallpaper)
|
||||
@@ -370,10 +370,10 @@ Singleton {
|
||||
|
||||
Process {
|
||||
id: cyclingProcess
|
||||
|
||||
|
||||
property string targetScreenName: ""
|
||||
property string currentWallpaper: ""
|
||||
|
||||
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
@@ -404,10 +404,10 @@ Singleton {
|
||||
|
||||
Process {
|
||||
id: prevCyclingProcess
|
||||
|
||||
|
||||
property string targetScreenName: ""
|
||||
property string currentWallpaper: ""
|
||||
|
||||
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
|
||||
@@ -75,7 +75,7 @@ Singleton {
|
||||
"96": "thunderstorm",
|
||||
"99": "thunderstorm"
|
||||
})
|
||||
|
||||
|
||||
property var nightWeatherIcons: ({
|
||||
"0": "clear_night",
|
||||
"1": "clear_night",
|
||||
@@ -114,7 +114,7 @@ Singleton {
|
||||
const iconMap = isDay ? weatherIcons : nightWeatherIcons
|
||||
return iconMap[String(code)] || "cloud"
|
||||
}
|
||||
|
||||
|
||||
function getWeatherCondition(code) {
|
||||
const conditions = {
|
||||
"0": "Clear",
|
||||
@@ -148,10 +148,10 @@ Singleton {
|
||||
}
|
||||
return conditions[String(code)] || "Unknown"
|
||||
}
|
||||
|
||||
|
||||
function formatTime(isoString) {
|
||||
if (!isoString) return "--"
|
||||
|
||||
|
||||
try {
|
||||
const date = new Date(isoString)
|
||||
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
||||
@@ -160,15 +160,15 @@ Singleton {
|
||||
return "--"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function formatForecastDay(isoString, index) {
|
||||
if (!isoString) return "--"
|
||||
|
||||
|
||||
try {
|
||||
const date = new Date(isoString)
|
||||
if (index === 0) return I18n.tr("Today")
|
||||
if (index === 1) return I18n.tr("Tomorrow")
|
||||
|
||||
|
||||
const locale = Qt.locale()
|
||||
return locale.dayName(date.getDay(), Locale.ShortFormat)
|
||||
} catch (e) {
|
||||
@@ -180,7 +180,7 @@ Singleton {
|
||||
if (!location) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
const params = [
|
||||
"latitude=" + location.latitude,
|
||||
"longitude=" + location.longitude,
|
||||
@@ -189,14 +189,14 @@ Singleton {
|
||||
"timezone=auto",
|
||||
"forecast_days=7"
|
||||
]
|
||||
|
||||
|
||||
if (SettingsData.useFahrenheit) {
|
||||
params.push("temperature_unit=fahrenheit")
|
||||
}
|
||||
|
||||
|
||||
return "https://api.open-meteo.com/v1/forecast?" + params.join('&')
|
||||
}
|
||||
|
||||
|
||||
function getGeocodingUrl(query) {
|
||||
return "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(query) + "&count=1&language=en&format=json"
|
||||
}
|
||||
@@ -229,25 +229,25 @@ Singleton {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const cityName = SettingsData.weatherLocation
|
||||
if (cityName) {
|
||||
getLocationFromCity(cityName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getLocationFromCoords(lat, lon) {
|
||||
const url = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lon + "&format=json&addressdetails=1&accept-language=en"
|
||||
reverseGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat(["-H", "User-Agent: DankMaterialShell Weather Widget", url])
|
||||
reverseGeocodeFetcher.running = true
|
||||
}
|
||||
|
||||
|
||||
function getLocationFromCity(city) {
|
||||
cityGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat([getGeocodingUrl(city)])
|
||||
cityGeocodeFetcher.running = true
|
||||
}
|
||||
|
||||
|
||||
function getLocationFromIP() {
|
||||
ipLocationFetcher.running = true
|
||||
}
|
||||
@@ -287,7 +287,7 @@ Singleton {
|
||||
root.lastFetchTime = 0 // Reset throttle
|
||||
fetchWeather()
|
||||
}
|
||||
|
||||
|
||||
function nextInterval() {
|
||||
const jitter = Math.floor(Math.random() * 15000) - 7500
|
||||
return Math.max(60000, root.updateInterval + jitter)
|
||||
@@ -324,7 +324,7 @@ Singleton {
|
||||
id: ipLocationFetcher
|
||||
command: lowPriorityCmd.concat(curlBaseCmd).concat(["http://ipinfo.io/json"])
|
||||
running: false
|
||||
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const raw = text.trim()
|
||||
@@ -337,23 +337,23 @@ Singleton {
|
||||
const data = JSON.parse(raw)
|
||||
const coords = data.loc
|
||||
const city = data.city
|
||||
|
||||
|
||||
if (!coords || !city) {
|
||||
throw new Error("Missing location data")
|
||||
}
|
||||
|
||||
|
||||
const coordsParts = coords.split(",")
|
||||
if (coordsParts.length !== 2) {
|
||||
throw new Error("Invalid coordinates format")
|
||||
}
|
||||
|
||||
|
||||
const lat = parseFloat(coordsParts[0])
|
||||
const lon = parseFloat(coordsParts[1])
|
||||
|
||||
|
||||
if (isNaN(lat) || isNaN(lon)) {
|
||||
throw new Error("Invalid coordinate values")
|
||||
}
|
||||
|
||||
|
||||
root.location = {
|
||||
city: city,
|
||||
latitude: lat,
|
||||
@@ -365,18 +365,18 @@ Singleton {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode !== 0) {
|
||||
root.handleWeatherFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Process {
|
||||
id: reverseGeocodeFetcher
|
||||
running: false
|
||||
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const raw = text.trim()
|
||||
@@ -388,32 +388,32 @@ Singleton {
|
||||
try {
|
||||
const data = JSON.parse(raw)
|
||||
const address = data.address || {}
|
||||
|
||||
|
||||
root.location = {
|
||||
city: address.hamlet || address.city || address.town || address.village || "Unknown",
|
||||
country: address.country || "Unknown",
|
||||
latitude: parseFloat(data.lat),
|
||||
longitude: parseFloat(data.lon)
|
||||
}
|
||||
|
||||
|
||||
fetchWeather()
|
||||
} catch (e) {
|
||||
root.handleWeatherFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode !== 0) {
|
||||
root.handleWeatherFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Process {
|
||||
id: cityGeocodeFetcher
|
||||
running: false
|
||||
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const raw = text.trim()
|
||||
@@ -425,27 +425,27 @@ Singleton {
|
||||
try {
|
||||
const data = JSON.parse(raw)
|
||||
const results = data.results
|
||||
|
||||
|
||||
if (!results || results.length === 0) {
|
||||
throw new Error("No results found")
|
||||
}
|
||||
|
||||
|
||||
const result = results[0]
|
||||
|
||||
|
||||
root.location = {
|
||||
city: result.name,
|
||||
country: result.country,
|
||||
latitude: result.latitude,
|
||||
longitude: result.longitude
|
||||
}
|
||||
|
||||
|
||||
fetchWeather()
|
||||
} catch (e) {
|
||||
root.handleWeatherFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode !== 0) {
|
||||
root.handleWeatherFailure()
|
||||
@@ -467,7 +467,7 @@ Singleton {
|
||||
|
||||
try {
|
||||
const data = JSON.parse(raw)
|
||||
|
||||
|
||||
if (!data.current || !data.daily) {
|
||||
throw new Error("Required weather data fields missing")
|
||||
}
|
||||
@@ -475,12 +475,12 @@ Singleton {
|
||||
const current = data.current
|
||||
const daily = data.daily
|
||||
const currentUnits = data.current_units || {}
|
||||
|
||||
|
||||
const tempC = current.temperature_2m || 0
|
||||
const tempF = SettingsData.useFahrenheit ? tempC : (tempC * 9/5 + 32)
|
||||
const feelsLikeC = current.apparent_temperature || tempC
|
||||
const feelsLikeF = SettingsData.useFahrenheit ? feelsLikeC : (feelsLikeC * 9/5 + 32)
|
||||
|
||||
|
||||
const forecast = []
|
||||
if (daily.time && daily.time.length > 0) {
|
||||
for (let i = 0; i < Math.min(daily.time.length, 7); i++) {
|
||||
@@ -488,7 +488,7 @@ Singleton {
|
||||
const tempMaxC = daily.temperature_2m_max?.[i] || 0
|
||||
const tempMinF = SettingsData.useFahrenheit ? tempMinC : (tempMinC * 9/5 + 32)
|
||||
const tempMaxF = SettingsData.useFahrenheit ? tempMaxC : (tempMaxC * 9/5 + 32)
|
||||
|
||||
|
||||
forecast.push({
|
||||
"day": formatForecastDay(daily.time[i], i),
|
||||
"wCode": daily.weather_code?.[i] || 0,
|
||||
@@ -502,7 +502,7 @@ Singleton {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
root.weather = {
|
||||
"available": true,
|
||||
"loading": false,
|
||||
@@ -577,7 +577,7 @@ Singleton {
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
||||
|
||||
SettingsData.weatherCoordinatesChanged.connect(() => {
|
||||
root.location = null
|
||||
root.weather = {
|
||||
@@ -635,7 +635,7 @@ Singleton {
|
||||
root.lastFetchTime = 0
|
||||
root.forceRefresh()
|
||||
})
|
||||
|
||||
|
||||
SettingsData.useFahrenheitChanged.connect(() => {
|
||||
root.lastFetchTime = 0
|
||||
root.forceRefresh()
|
||||
|
||||
@@ -42,91 +42,91 @@ Item {
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
z: 0
|
||||
layer.enabled: false
|
||||
|
||||
|
||||
readonly property real centerX: width / 2
|
||||
readonly property real centerY: height / 2
|
||||
readonly property real baseRadius: Math.min(width, height) * 0.41 * root.animationScale
|
||||
readonly property int segments: 28
|
||||
|
||||
|
||||
property var audioLevels: {
|
||||
if (!CavaService.cavaAvailable || CavaService.values.length === 0) {
|
||||
return [0.5, 0.3, 0.7, 0.4, 0.6, 0.5, 0.8, 0.2, 0.9, 0.6]
|
||||
}
|
||||
return CavaService.values
|
||||
}
|
||||
|
||||
|
||||
property var smoothedLevels: [0.5, 0.3, 0.7, 0.4, 0.6, 0.5, 0.8, 0.2, 0.9, 0.6]
|
||||
property var cubics: []
|
||||
|
||||
onAudioLevelsChanged: updatePath()
|
||||
|
||||
|
||||
FrameAnimation {
|
||||
running: morphingBlob.visible
|
||||
onTriggered: morphingBlob.updatePath()
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: cubicSegment
|
||||
PathCubic {}
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
shapePath.pathElements.push(Qt.createQmlObject(
|
||||
'import QtQuick; import QtQuick.Shapes; PathMove {}', shapePath
|
||||
))
|
||||
|
||||
|
||||
for (let i = 0; i < segments; i++) {
|
||||
const seg = cubicSegment.createObject(shapePath)
|
||||
shapePath.pathElements.push(seg)
|
||||
cubics.push(seg)
|
||||
}
|
||||
|
||||
|
||||
updatePath()
|
||||
}
|
||||
|
||||
|
||||
function expSmooth(prev, next, alpha) {
|
||||
return prev + alpha * (next - prev)
|
||||
}
|
||||
|
||||
|
||||
function updatePath() {
|
||||
if (cubics.length === 0) return
|
||||
|
||||
|
||||
for (let i = 0; i < Math.min(smoothedLevels.length, audioLevels.length); i++) {
|
||||
smoothedLevels[i] = expSmooth(smoothedLevels[i], audioLevels[i], 0.35)
|
||||
}
|
||||
|
||||
|
||||
const points = []
|
||||
for (let i = 0; i < segments; i++) {
|
||||
const angle = (i / segments) * 2 * Math.PI
|
||||
const audioIndex = i % Math.min(smoothedLevels.length, 10)
|
||||
|
||||
|
||||
const rawLevel = smoothedLevels[audioIndex] || 0
|
||||
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100
|
||||
const normalizedLevel = scaledLevel / 100
|
||||
const audioLevel = Math.max(0.15, normalizedLevel) * 0.5
|
||||
|
||||
|
||||
const radius = baseRadius * (1.0 + audioLevel)
|
||||
const x = centerX + Math.cos(angle) * radius
|
||||
const y = centerY + Math.sin(angle) * radius
|
||||
points.push({x: x, y: y})
|
||||
}
|
||||
|
||||
|
||||
const startMove = shapePath.pathElements[0]
|
||||
startMove.x = points[0].x
|
||||
startMove.y = points[0].y
|
||||
|
||||
|
||||
const tension = 0.5
|
||||
for (let i = 0; i < segments; i++) {
|
||||
const p0 = points[(i - 1 + segments) % segments]
|
||||
const p1 = points[i]
|
||||
const p2 = points[(i + 1) % segments]
|
||||
const p3 = points[(i + 2) % segments]
|
||||
|
||||
|
||||
const c1x = p1.x + (p2.x - p0.x) * tension / 3
|
||||
const c1y = p1.y + (p2.y - p0.y) * tension / 3
|
||||
const c2x = p2.x - (p3.x - p1.x) * tension / 3
|
||||
const c2y = p2.y - (p3.y - p1.y) * tension / 3
|
||||
|
||||
|
||||
const seg = cubics[i]
|
||||
seg.control1X = c1x
|
||||
seg.control1Y = c1y
|
||||
@@ -136,7 +136,7 @@ Item {
|
||||
seg.y = p2.y
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ShapePath {
|
||||
id: shapePath
|
||||
fillColor: Theme.primary
|
||||
|
||||
@@ -98,10 +98,10 @@ Item {
|
||||
bottomRightRadius: 0
|
||||
color: Theme.primary
|
||||
visible: false
|
||||
|
||||
|
||||
property bool animationEnabled: false
|
||||
property bool initialSetupComplete: false
|
||||
|
||||
|
||||
Behavior on x {
|
||||
enabled: indicator.animationEnabled
|
||||
NumberAnimation {
|
||||
@@ -109,7 +109,7 @@ Item {
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Behavior on width {
|
||||
enabled: indicator.animationEnabled
|
||||
NumberAnimation {
|
||||
@@ -130,21 +130,21 @@ Item {
|
||||
if (tabRepeater.count === 0 || currentIndex < 0 || currentIndex >= tabRepeater.count) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const item = tabRepeater.itemAt(currentIndex)
|
||||
if (!item || item.isAction) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const tabPos = item.mapToItem(tabBar, 0, 0)
|
||||
const tabCenterX = tabPos.x + item.width / 2
|
||||
const indicatorWidth = 60
|
||||
|
||||
|
||||
if (tabPos.x < 10 && currentIndex > 0) {
|
||||
Qt.callLater(() => updateIndicator(enableAnimation))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
indicator.animationEnabled = enableAnimation
|
||||
indicator.width = indicatorWidth
|
||||
indicator.x = tabCenterX - indicatorWidth / 2
|
||||
|
||||
Reference in New Issue
Block a user