mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
cleanup and qmlfmt some modules
This commit is contained in:
@@ -23,10 +23,6 @@ DankPopout {
|
|||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, screen) {
|
function setTriggerPosition(x, y, width, section, screen) {
|
||||||
triggerX = x
|
triggerX = x
|
||||||
triggerY = y
|
triggerY = y
|
||||||
@@ -46,10 +42,10 @@ DankPopout {
|
|||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item && contentLoader.item.searchField) {
|
if (contentLoader.item && contentLoader.item.searchField) {
|
||||||
contentLoader.item.searchField.forceActiveFocus()
|
contentLoader.item.searchField.forceActiveFocus()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
AppLauncher {
|
AppLauncher {
|
||||||
@@ -57,7 +53,7 @@ DankPopout {
|
|||||||
|
|
||||||
viewMode: SettingsData.appLauncherViewMode
|
viewMode: SettingsData.appLauncherViewMode
|
||||||
gridColumns: 4
|
gridColumns: 4
|
||||||
onAppLaunched: appDrawerPopout.hide()
|
onAppLaunched: appDrawerPopout.close()
|
||||||
onViewModeSelected: function (mode) {
|
onViewModeSelected: function (mode) {
|
||||||
SettingsData.setAppLauncherViewMode(mode)
|
SettingsData.setAppLauncherViewMode(mode)
|
||||||
}
|
}
|
||||||
@@ -74,34 +70,30 @@ DankPopout {
|
|||||||
antialiasing: true
|
antialiasing: true
|
||||||
smooth: true
|
smooth: true
|
||||||
|
|
||||||
Rectangle {
|
// Multi-layer border effect
|
||||||
anchors.fill: parent
|
Repeater {
|
||||||
anchors.margins: -3
|
model: [{
|
||||||
color: "transparent"
|
"margin": -3,
|
||||||
radius: parent.radius + 3
|
"color": Qt.rgba(0, 0, 0, 0.05),
|
||||||
border.color: Qt.rgba(0, 0, 0, 0.05)
|
"z": -3
|
||||||
border.width: 1
|
}, {
|
||||||
z: -3
|
"margin": -2,
|
||||||
}
|
"color": Qt.rgba(0, 0, 0, 0.08),
|
||||||
|
"z": -2
|
||||||
Rectangle {
|
}, {
|
||||||
anchors.fill: parent
|
"margin": 0,
|
||||||
anchors.margins: -2
|
"color": Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12),
|
||||||
color: "transparent"
|
"z": -1
|
||||||
radius: parent.radius + 2
|
}]
|
||||||
border.color: Qt.rgba(0, 0, 0, 0.08)
|
Rectangle {
|
||||||
border.width: 1
|
anchors.fill: parent
|
||||||
z: -2
|
anchors.margins: modelData.margin
|
||||||
}
|
color: "transparent"
|
||||||
|
radius: parent.radius + Math.abs(modelData.margin)
|
||||||
Rectangle {
|
border.color: modelData.color
|
||||||
anchors.fill: parent
|
border.width: 1
|
||||||
color: "transparent"
|
z: modelData.z
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
}
|
||||||
Theme.outline.b, 0.12)
|
|
||||||
border.width: 1
|
|
||||||
radius: parent.radius
|
|
||||||
z: -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -109,31 +101,30 @@ DankPopout {
|
|||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
|
readonly property var keyMappings: {
|
||||||
|
const mappings = {}
|
||||||
|
mappings[Qt.Key_Escape] = () => appDrawerPopout.close()
|
||||||
|
mappings[Qt.Key_Down] = () => appLauncher.selectNext()
|
||||||
|
mappings[Qt.Key_Up] = () => appLauncher.selectPrevious()
|
||||||
|
mappings[Qt.Key_Return] = () => appLauncher.launchSelected()
|
||||||
|
mappings[Qt.Key_Enter] = () => appLauncher.launchSelected()
|
||||||
|
|
||||||
|
if (appLauncher.viewMode === "grid") {
|
||||||
|
mappings[Qt.Key_Right] = () => appLauncher.selectNextInRow()
|
||||||
|
mappings[Qt.Key_Left] = () => appLauncher.selectPreviousInRow()
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappings
|
||||||
|
}
|
||||||
|
|
||||||
Keys.onPressed: function (event) {
|
Keys.onPressed: function (event) {
|
||||||
if (event.key === Qt.Key_Escape) {
|
if (keyMappings[event.key]) {
|
||||||
appDrawerPopout.close()
|
keyMappings[event.key]()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if (event.key === Qt.Key_Down) {
|
return
|
||||||
appLauncher.selectNext()
|
}
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Up) {
|
if (!searchField.activeFocus && event.text && /[a-zA-Z0-9\s]/.test(event.text)) {
|
||||||
appLauncher.selectPrevious()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Right
|
|
||||||
&& appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectNextInRow()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Left
|
|
||||||
&& appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectPreviousInRow()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Return
|
|
||||||
|| event.key === Qt.Key_Enter) {
|
|
||||||
appLauncher.launchSelected()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (!searchField.activeFocus && event.text
|
|
||||||
&& event.text.length > 0 && event.text.match(
|
|
||||||
/[a-zA-Z0-9\\s]/)) {
|
|
||||||
searchField.forceActiveFocus()
|
searchField.forceActiveFocus()
|
||||||
searchField.insertText(event.text)
|
searchField.insertText(event.text)
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
@@ -178,15 +169,8 @@ DankPopout {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 52
|
height: 52
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
backgroundColor: Qt.rgba(
|
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
|
||||||
Theme.surfaceVariant.r,
|
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
Theme.getContentBackgroundAlpha(
|
|
||||||
) * 0.7)
|
|
||||||
normalBorderColor: Qt.rgba(Theme.outline.r,
|
|
||||||
Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.3)
|
|
||||||
focusedBorderColor: Theme.primary
|
focusedBorderColor: Theme.primary
|
||||||
leftIconName: "search"
|
leftIconName: "search"
|
||||||
leftIconSize: Theme.iconSize
|
leftIconSize: Theme.iconSize
|
||||||
@@ -204,28 +188,34 @@ DankPopout {
|
|||||||
if (event.key === Qt.Key_Escape) {
|
if (event.key === Qt.Key_Escape) {
|
||||||
appDrawerPopout.close()
|
appDrawerPopout.close()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if ((event.key === Qt.Key_Return
|
return
|
||||||
|| event.key === Qt.Key_Enter)
|
}
|
||||||
&& text.length > 0) {
|
|
||||||
if (appLauncher.keyboardNavigationActive
|
const isEnterKey = [Qt.Key_Return, Qt.Key_Enter].includes(event.key)
|
||||||
&& appLauncher.model.count > 0) {
|
const hasText = text.length > 0
|
||||||
|
|
||||||
|
if (isEnterKey && hasText) {
|
||||||
|
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0) {
|
||||||
appLauncher.launchSelected()
|
appLauncher.launchSelected()
|
||||||
} else if (appLauncher.model.count > 0) {
|
} else if (appLauncher.model.count > 0) {
|
||||||
var firstApp = appLauncher.model.get(0)
|
appLauncher.launchApp(appLauncher.model.get(0))
|
||||||
appLauncher.launchApp(firstApp)
|
|
||||||
}
|
}
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if (event.key === Qt.Key_Down || event.key
|
return
|
||||||
=== Qt.Key_Up || event.key === Qt.Key_Left || event.key
|
|
||||||
=== Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
|
||||||
event.accepted = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const navigationKeys = [Qt.Key_Down, Qt.Key_Up, Qt.Key_Left, Qt.Key_Right]
|
||||||
|
const isNavigationKey = navigationKeys.includes(event.key)
|
||||||
|
const isEmptyEnter = isEnterKey && !hasText
|
||||||
|
|
||||||
|
event.accepted = !(isNavigationKey || isEmptyEnter)
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
if (!appDrawerPopout.shouldBeVisible)
|
if (!appDrawerPopout.shouldBeVisible) {
|
||||||
searchField.clearFocus()
|
searchField.focus = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target: appDrawerPopout
|
target: appDrawerPopout
|
||||||
@@ -268,14 +258,8 @@ DankPopout {
|
|||||||
circular: false
|
circular: false
|
||||||
iconName: "view_list"
|
iconName: "view_list"
|
||||||
iconSize: 20
|
iconSize: 20
|
||||||
iconColor: appLauncher.viewMode
|
iconColor: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
|
||||||
=== "list" ? Theme.primary : Theme.surfaceText
|
backgroundColor: appLauncher.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
backgroundColor: appLauncher.viewMode
|
|
||||||
=== "list" ? Qt.rgba(
|
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appLauncher.setViewMode("list")
|
appLauncher.setViewMode("list")
|
||||||
}
|
}
|
||||||
@@ -286,14 +270,8 @@ DankPopout {
|
|||||||
circular: false
|
circular: false
|
||||||
iconName: "grid_view"
|
iconName: "grid_view"
|
||||||
iconSize: 20
|
iconSize: 20
|
||||||
iconColor: appLauncher.viewMode
|
iconColor: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
|
||||||
=== "grid" ? Theme.primary : Theme.surfaceText
|
backgroundColor: appLauncher.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
backgroundColor: appLauncher.viewMode
|
|
||||||
=== "grid" ? Qt.rgba(
|
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appLauncher.setViewMode("grid")
|
appLauncher.setViewMode("grid")
|
||||||
}
|
}
|
||||||
@@ -310,11 +288,8 @@ DankPopout {
|
|||||||
return parent.height - usedHeight
|
return parent.height - usedHeight
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceVariant.r,
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
|
||||||
Theme.surfaceVariant.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
|
||||||
Theme.surfaceVariant.b, 0.1)
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.05)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
DankListView {
|
DankListView {
|
||||||
@@ -408,11 +383,7 @@ DankPopout {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: (model.name
|
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||||
&& model.name.length
|
|
||||||
> 0) ? model.name.charAt(
|
|
||||||
0).toUpperCase(
|
|
||||||
) : "A"
|
|
||||||
font.pixelSize: appList.iconSize * 0.4
|
font.pixelSize: appList.iconSize * 0.4
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
@@ -440,9 +411,7 @@ DankPopout {
|
|||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
visible: appList.showDescription
|
visible: appList.showDescription && model.comment && model.comment.length > 0
|
||||||
&& model.comment
|
|
||||||
&& model.comment.length > 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,8 +425,7 @@ DankPopout {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
z: 10
|
z: 10
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (appList.hoverUpdatesSelection
|
if (appList.hoverUpdatesSelection && !appList.keyboardNavigationActive)
|
||||||
&& !appList.keyboardNavigationActive)
|
|
||||||
appList.currentIndex = index
|
appList.currentIndex = index
|
||||||
}
|
}
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
@@ -465,16 +433,10 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
appList.itemClicked(
|
appList.itemClicked(index, model)
|
||||||
index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
var panelPos = mapToItem(
|
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y)
|
||||||
contextMenu.parent,
|
appList.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
||||||
mouse.x, mouse.y)
|
|
||||||
appList.itemRightClicked(
|
|
||||||
index, model,
|
|
||||||
panelPos.x,
|
|
||||||
panelPos.y)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,8 +470,7 @@ DankPopout {
|
|||||||
if (index < 0 || index >= count)
|
if (index < 0 || index >= count)
|
||||||
return
|
return
|
||||||
|
|
||||||
var itemY = Math.floor(
|
var itemY = Math.floor(index / actualColumns) * cellHeight
|
||||||
index / actualColumns) * cellHeight
|
|
||||||
var itemBottom = itemY + cellHeight
|
var itemBottom = itemY + cellHeight
|
||||||
if (itemY < contentY)
|
if (itemY < contentY)
|
||||||
contentY = itemY
|
contentY = itemY
|
||||||
@@ -524,8 +485,7 @@ DankPopout {
|
|||||||
clip: true
|
clip: true
|
||||||
cellWidth: baseCellWidth
|
cellWidth: baseCellWidth
|
||||||
cellHeight: baseCellHeight
|
cellHeight: baseCellHeight
|
||||||
leftMargin: Math.max(Theme.spacingS,
|
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
|
||||||
remainingSpace / 2)
|
|
||||||
rightMargin: leftMargin
|
rightMargin: leftMargin
|
||||||
focus: true
|
focus: true
|
||||||
interactive: true
|
interactive: true
|
||||||
@@ -560,12 +520,7 @@ DankPopout {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property int iconSize: Math.min(
|
property int iconSize: Math.min(appGrid.maxIconSize, Math.max(appGrid.minIconSize, appGrid.cellWidth * appGrid.iconSizeRatio))
|
||||||
appGrid.maxIconSize,
|
|
||||||
Math.max(
|
|
||||||
appGrid.minIconSize,
|
|
||||||
appGrid.cellWidth
|
|
||||||
* appGrid.iconSizeRatio))
|
|
||||||
|
|
||||||
width: iconSize
|
width: iconSize
|
||||||
height: iconSize
|
height: iconSize
|
||||||
@@ -591,14 +546,8 @@ DankPopout {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: (model.name
|
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||||
&& model.name.length
|
font.pixelSize: Math.min(28, parent.width * 0.5)
|
||||||
> 0) ? model.name.charAt(
|
|
||||||
0).toUpperCase(
|
|
||||||
) : "A"
|
|
||||||
font.pixelSize: Math.min(
|
|
||||||
28,
|
|
||||||
parent.width * 0.5)
|
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
}
|
}
|
||||||
@@ -628,8 +577,7 @@ DankPopout {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
z: 10
|
z: 10
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (appGrid.hoverUpdatesSelection
|
if (appGrid.hoverUpdatesSelection && !appGrid.keyboardNavigationActive)
|
||||||
&& !appGrid.keyboardNavigationActive)
|
|
||||||
appGrid.currentIndex = index
|
appGrid.currentIndex = index
|
||||||
}
|
}
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
@@ -637,16 +585,10 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
appGrid.itemClicked(
|
appGrid.itemClicked(index, model)
|
||||||
index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
var panelPos = mapToItem(
|
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y)
|
||||||
contextMenu.parent,
|
appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
||||||
mouse.x, mouse.y)
|
|
||||||
appGrid.itemRightClicked(
|
|
||||||
index, model,
|
|
||||||
panelPos.x,
|
|
||||||
panelPos.y)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -664,6 +606,9 @@ DankPopout {
|
|||||||
property var currentApp: null
|
property var currentApp: null
|
||||||
property bool menuVisible: false
|
property bool menuVisible: false
|
||||||
|
|
||||||
|
readonly property string appId: (currentApp && currentApp.desktopEntry) ? (currentApp.desktopEntry.id || currentApp.desktopEntry.execString || "") : ""
|
||||||
|
readonly property bool isPinned: appId && SessionData.isPinnedApp(appId)
|
||||||
|
|
||||||
function show(x, y, app) {
|
function show(x, y, app) {
|
||||||
currentApp = app
|
currentApp = app
|
||||||
|
|
||||||
@@ -681,12 +626,8 @@ DankPopout {
|
|||||||
finalY = y - menuHeight - 8
|
finalY = y - menuHeight - 8
|
||||||
}
|
}
|
||||||
|
|
||||||
finalX = Math.max(
|
finalX = Math.max(8, Math.min(finalX, appDrawerPopout.popupWidth - menuWidth - 8))
|
||||||
8, Math.min(finalX,
|
finalY = Math.max(8, Math.min(finalY, appDrawerPopout.popupHeight - menuHeight - 8))
|
||||||
appDrawerPopout.popupWidth - menuWidth - 8))
|
|
||||||
finalY = Math.max(8, Math.min(
|
|
||||||
finalY,
|
|
||||||
appDrawerPopout.popupHeight - menuHeight - 8))
|
|
||||||
|
|
||||||
contextMenu.x = finalX
|
contextMenu.x = finalX
|
||||||
contextMenu.y = finalY
|
contextMenu.y = finalY
|
||||||
@@ -706,8 +647,7 @@ DankPopout {
|
|||||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
z: 1000
|
z: 1000
|
||||||
opacity: menuVisible ? 1 : 0
|
opacity: menuVisible ? 1 : 0
|
||||||
@@ -735,11 +675,7 @@ DankPopout {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 32
|
height: 32
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: pinMouseArea.containsMouse ? Qt.rgba(
|
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -748,17 +684,7 @@ DankPopout {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: {
|
name: contextMenu.isPinned ? "keep_off" : "push_pin"
|
||||||
if (!contextMenu.currentApp
|
|
||||||
|| !contextMenu.currentApp.desktopEntry)
|
|
||||||
return "push_pin"
|
|
||||||
|
|
||||||
var appId = contextMenu.currentApp.desktopEntry.id
|
|
||||||
|| contextMenu.currentApp.desktopEntry.execString
|
|
||||||
|| ""
|
|
||||||
return SessionData.isPinnedApp(
|
|
||||||
appId) ? "keep_off" : "push_pin"
|
|
||||||
}
|
|
||||||
size: Theme.iconSize - 2
|
size: Theme.iconSize - 2
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
@@ -766,17 +692,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: contextMenu.isPinned ? "Unpin from Dock" : "Pin to Dock"
|
||||||
if (!contextMenu.currentApp
|
|
||||||
|| !contextMenu.currentApp.desktopEntry)
|
|
||||||
return "Pin to Dock"
|
|
||||||
|
|
||||||
var appId = contextMenu.currentApp.desktopEntry.id
|
|
||||||
|| contextMenu.currentApp.desktopEntry.execString
|
|
||||||
|| ""
|
|
||||||
return SessionData.isPinnedApp(
|
|
||||||
appId) ? "Unpin from Dock" : "Pin to Dock"
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -791,17 +707,15 @@ DankPopout {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!contextMenu.currentApp
|
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) {
|
||||||
|| !contextMenu.currentApp.desktopEntry)
|
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var appId = contextMenu.currentApp.desktopEntry.id
|
if (contextMenu.isPinned) {
|
||||||
|| contextMenu.currentApp.desktopEntry.execString
|
SessionData.removePinnedApp(contextMenu.appId)
|
||||||
|| ""
|
} else {
|
||||||
if (SessionData.isPinnedApp(appId))
|
SessionData.addPinnedApp(contextMenu.appId)
|
||||||
SessionData.removePinnedApp(appId)
|
}
|
||||||
else
|
|
||||||
SessionData.addPinnedApp(appId)
|
|
||||||
contextMenu.close()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -817,8 +731,7 @@ DankPopout {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
Theme.outline.b, 0.2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,11 +739,7 @@ DankPopout {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 32
|
height: 32
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: launchMouseArea.containsMouse ? Qt.rgba(
|
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|||||||
@@ -17,20 +17,12 @@ Item {
|
|||||||
property bool debounceSearch: true
|
property bool debounceSearch: true
|
||||||
property int debounceInterval: 50
|
property int debounceInterval: 50
|
||||||
property bool keyboardNavigationActive: false
|
property bool keyboardNavigationActive: false
|
||||||
property var categories: {
|
readonly property var categories: {
|
||||||
var allCategories = AppSearchService.getAllCategories().filter(cat => {
|
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
|
||||||
return cat !== "Education"
|
const result = ["All"]
|
||||||
&& cat !== "Science"
|
return result.concat(allCategories.filter(cat => cat !== "All"))
|
||||||
})
|
|
||||||
var result = ["All"]
|
|
||||||
return result.concat(allCategories.filter(cat => {
|
|
||||||
return cat !== "All"
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
property var categoryIcons: categories.map(category => {
|
readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
||||||
return AppSearchService.getCategoryIcon(
|
|
||||||
category)
|
|
||||||
})
|
|
||||||
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
||||||
property alias model: filteredModel
|
property alias model: filteredModel
|
||||||
property var _watchApplications: AppSearchService.applications
|
property var _watchApplications: AppSearchService.applications
|
||||||
@@ -43,116 +35,96 @@ Item {
|
|||||||
filteredModel.clear()
|
filteredModel.clear()
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
keyboardNavigationActive = false
|
keyboardNavigationActive = false
|
||||||
var apps = []
|
|
||||||
|
let apps = []
|
||||||
if (searchQuery.length === 0) {
|
if (searchQuery.length === 0) {
|
||||||
if (selectedCategory === "All") {
|
apps = selectedCategory === "All" ? AppSearchService.getAppsInCategory("All") : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
||||||
apps = AppSearchService.getAppsInCategory(
|
|
||||||
"All") // HACK: Use function call instead of property
|
|
||||||
} else {
|
|
||||||
var categoryApps = AppSearchService.getAppsInCategory(
|
|
||||||
selectedCategory)
|
|
||||||
apps = categoryApps.slice(0, maxResults)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (selectedCategory === "All") {
|
if (selectedCategory === "All") {
|
||||||
apps = AppSearchService.searchApplications(searchQuery)
|
apps = AppSearchService.searchApplications(searchQuery)
|
||||||
} else {
|
} else {
|
||||||
var categoryApps = AppSearchService.getAppsInCategory(
|
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
||||||
selectedCategory)
|
|
||||||
if (categoryApps.length > 0) {
|
if (categoryApps.length > 0) {
|
||||||
var allSearchResults = AppSearchService.searchApplications(
|
const allSearchResults = AppSearchService.searchApplications(searchQuery)
|
||||||
searchQuery)
|
const categoryNames = new Set(categoryApps.map(app => app.name))
|
||||||
var categoryNames = new Set(categoryApps.map(app => {
|
apps = allSearchResults.filter(searchApp => categoryNames.has(searchApp.name)).slice(0, maxResults)
|
||||||
return app.name
|
|
||||||
}))
|
|
||||||
apps = allSearchResults.filter(searchApp => {
|
|
||||||
return categoryNames.has(
|
|
||||||
searchApp.name)
|
|
||||||
}).slice(0, maxResults)
|
|
||||||
} else {
|
} else {
|
||||||
apps = []
|
apps = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (searchQuery.length === 0)
|
|
||||||
apps = apps.sort(function (a, b) {
|
|
||||||
var aId = a.id || (a.execString || a.exec || "")
|
|
||||||
var bId = b.id || (b.execString || b.exec || "")
|
|
||||||
var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
|
|
||||||
var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
|
|
||||||
if (aUsage !== bUsage)
|
|
||||||
return bUsage - aUsage
|
|
||||||
|
|
||||||
return (a.name || "").localeCompare(b.name || "")
|
if (searchQuery.length === 0) {
|
||||||
})
|
apps = apps.sort((a, b) => {
|
||||||
|
const aId = a.id || a.execString || a.exec || ""
|
||||||
|
const bId = b.id || b.execString || b.exec || ""
|
||||||
|
const aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
|
||||||
|
const bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
|
||||||
|
if (aUsage !== bUsage) {
|
||||||
|
return bUsage - aUsage
|
||||||
|
}
|
||||||
|
return (a.name || "").localeCompare(b.name || "")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
apps.forEach(app => {
|
apps.forEach(app => {
|
||||||
if (app)
|
if (app) {
|
||||||
filteredModel.append({
|
filteredModel.append({
|
||||||
"name": app.name || "",
|
"name": app.name || "",
|
||||||
"exec": app.execString || "",
|
"exec": app.execString || "",
|
||||||
"icon": app.icon
|
"icon": app.icon || "application-x-executable",
|
||||||
|| "application-x-executable",
|
"comment": app.comment || "",
|
||||||
"comment": app.comment || "",
|
"categories": app.categories || [],
|
||||||
"categories": app.categories
|
"desktopEntry": app
|
||||||
|| [],
|
})
|
||||||
"desktopEntry": app
|
}
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNext() {
|
function selectNext() {
|
||||||
if (filteredModel.count > 0) {
|
if (filteredModel.count === 0) {
|
||||||
keyboardNavigationActive = true
|
return
|
||||||
if (viewMode === "grid") {
|
|
||||||
var newIndex = Math.min(selectedIndex + gridColumns,
|
|
||||||
filteredModel.count - 1)
|
|
||||||
selectedIndex = newIndex
|
|
||||||
} else {
|
|
||||||
selectedIndex = Math.min(selectedIndex + 1,
|
|
||||||
filteredModel.count - 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
keyboardNavigationActive = true
|
||||||
|
selectedIndex = viewMode === "grid" ? Math.min(selectedIndex + gridColumns, filteredModel.count - 1) : Math.min(selectedIndex + 1, filteredModel.count - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPrevious() {
|
function selectPrevious() {
|
||||||
if (filteredModel.count > 0) {
|
if (filteredModel.count === 0) {
|
||||||
keyboardNavigationActive = true
|
return
|
||||||
if (viewMode === "grid") {
|
|
||||||
var newIndex = Math.max(selectedIndex - gridColumns, 0)
|
|
||||||
selectedIndex = newIndex
|
|
||||||
} else {
|
|
||||||
selectedIndex = Math.max(selectedIndex - 1, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
keyboardNavigationActive = true
|
||||||
|
selectedIndex = viewMode === "grid" ? Math.max(selectedIndex - gridColumns, 0) : Math.max(selectedIndex - 1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNextInRow() {
|
function selectNextInRow() {
|
||||||
if (filteredModel.count > 0 && viewMode === "grid") {
|
if (filteredModel.count === 0 || viewMode !== "grid") {
|
||||||
keyboardNavigationActive = true
|
return
|
||||||
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
|
|
||||||
}
|
}
|
||||||
|
keyboardNavigationActive = true
|
||||||
|
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPreviousInRow() {
|
function selectPreviousInRow() {
|
||||||
if (filteredModel.count > 0 && viewMode === "grid") {
|
if (filteredModel.count === 0 || viewMode !== "grid") {
|
||||||
keyboardNavigationActive = true
|
return
|
||||||
selectedIndex = Math.max(selectedIndex - 1, 0)
|
|
||||||
}
|
}
|
||||||
|
keyboardNavigationActive = true
|
||||||
|
selectedIndex = Math.max(selectedIndex - 1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchSelected() {
|
function launchSelected() {
|
||||||
if (filteredModel.count > 0 && selectedIndex >= 0
|
if (filteredModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredModel.count) {
|
||||||
&& selectedIndex < filteredModel.count) {
|
return
|
||||||
var selectedApp = filteredModel.get(selectedIndex)
|
|
||||||
launchApp(selectedApp)
|
|
||||||
}
|
}
|
||||||
|
const selectedApp = filteredModel.get(selectedIndex)
|
||||||
|
launchApp(selectedApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchApp(appData) {
|
function launchApp(appData) {
|
||||||
if (!appData)
|
if (!appData) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
appData.desktopEntry.execute()
|
appData.desktopEntry.execute()
|
||||||
appLaunched(appData)
|
appLaunched(appData)
|
||||||
AppUsageHistoryData.addAppUsage(appData.desktopEntry)
|
AppUsageHistoryData.addAppUsage(appData.desktopEntry)
|
||||||
@@ -169,10 +141,11 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSearchQueryChanged: {
|
onSearchQueryChanged: {
|
||||||
if (debounceSearch)
|
if (debounceSearch) {
|
||||||
searchDebounceTimer.restart()
|
searchDebounceTimer.restart()
|
||||||
else
|
} else {
|
||||||
updateFilteredModel()
|
updateFilteredModel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onSelectedCategoryChanged: updateFilteredModel()
|
onSelectedCategoryChanged: updateFilteredModel()
|
||||||
onAppUsageRankingChanged: updateFilteredModel()
|
onAppUsageRankingChanged: updateFilteredModel()
|
||||||
|
|||||||
@@ -8,11 +8,25 @@ Item {
|
|||||||
|
|
||||||
property var categories: []
|
property var categories: []
|
||||||
property string selectedCategory: "All"
|
property string selectedCategory: "All"
|
||||||
property bool compact: false // For different layout styles
|
property bool compact: false
|
||||||
|
|
||||||
signal categorySelected(string category)
|
signal categorySelected(string category)
|
||||||
|
|
||||||
height: compact ? 36 : (72 + Theme.spacingS) // Single row vs two rows
|
readonly property int maxCompactItems: 8
|
||||||
|
readonly property int itemHeight: 36
|
||||||
|
readonly property color selectedBorderColor: "transparent"
|
||||||
|
readonly property color unselectedBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||||
|
|
||||||
|
function handleCategoryClick(category) {
|
||||||
|
selectedCategory = category
|
||||||
|
categorySelected(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getButtonWidth(itemCount, containerWidth) {
|
||||||
|
return itemCount > 0 ? (containerWidth - (itemCount - 1) * Theme.spacingS) / itemCount : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
height: compact ? itemHeight : (itemHeight * 2 + Theme.spacingS)
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
visible: compact
|
visible: compact
|
||||||
@@ -20,22 +34,16 @@ Item {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: categories.slice(0, Math.min(categories.length,
|
model: categories ? categories.slice(0, Math.min(categories.length || 0, maxCompactItems)) : []
|
||||||
8)) // Limit for space
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 36
|
property int itemCount: Math.min(categories ? categories.length || 0 : 0, maxCompactItems)
|
||||||
width: (parent.width - (Math.min(
|
|
||||||
categories.length,
|
height: root.itemHeight
|
||||||
8) - 1) * Theme.spacingS) / Math.min(
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
categories.length, 8)
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
Theme.outline.r,
|
|
||||||
Theme.outline.g,
|
|
||||||
Theme.outline.b,
|
|
||||||
0.3)
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -50,10 +58,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: root.handleCategoryClick(modelData)
|
||||||
selectedCategory = modelData
|
|
||||||
categorySelected(modelData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,27 +70,20 @@ Item {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
property var firstRowCategories: categories.slice(
|
|
||||||
0, Math.min(4,
|
|
||||||
categories.length))
|
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: parent.firstRowCategories
|
model: categories ? categories.slice(0, Math.min(4, categories.length || 0)) : []
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 36
|
property int itemCount: Math.min(4, categories ? categories.length || 0 : 0)
|
||||||
width: (parent.width - (parent.firstRowCategories.length - 1)
|
|
||||||
* Theme.spacingS) / parent.firstRowCategories.length
|
height: root.itemHeight
|
||||||
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
border.color: selectedCategory
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
=== modelData ? "transparent" : Qt.rgba(
|
|
||||||
Theme.outline.r,
|
|
||||||
Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.3)
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -100,37 +98,28 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: root.handleCategoryClick(modelData)
|
||||||
selectedCategory = modelData
|
|
||||||
categorySelected(modelData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
property var secondRowCategories: categories.slice(
|
|
||||||
4, categories.length)
|
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: secondRowCategories.length > 0
|
visible: categories && categories.length > 4
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: parent.secondRowCategories
|
model: categories && categories.length > 4 ? categories.slice(4) : []
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: 36
|
property int itemCount: categories && categories.length > 4 ? categories.length - 4 : 0
|
||||||
width: (parent.width - (parent.secondRowCategories.length - 1)
|
|
||||||
* Theme.spacingS) / parent.secondRowCategories.length
|
height: root.itemHeight
|
||||||
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
border.color: selectedCategory
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
=== modelData ? "transparent" : Qt.rgba(
|
|
||||||
Theme.outline.r,
|
|
||||||
Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.3)
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -145,10 +134,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: root.handleCategoryClick(modelData)
|
||||||
selectedCategory = modelData
|
|
||||||
categorySelected(modelData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,35 +12,31 @@ Column {
|
|||||||
property date selectedDate: new Date()
|
property date selectedDate: new Date()
|
||||||
|
|
||||||
function loadEventsForMonth() {
|
function loadEventsForMonth() {
|
||||||
if (!CalendarService || !CalendarService.khalAvailable)
|
if (!CalendarService || !CalendarService.khalAvailable) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstDay = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
|
||||||
|
const dayOfWeek = firstDay.getDay()
|
||||||
|
const startDate = new Date(firstDay)
|
||||||
|
startDate.setDate(startDate.getDate() - dayOfWeek - 7)
|
||||||
|
|
||||||
|
const lastDay = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 0)
|
||||||
|
const endDate = new Date(lastDay)
|
||||||
|
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay()) + 7)
|
||||||
|
|
||||||
let firstDay = new Date(displayDate.getFullYear(),
|
|
||||||
displayDate.getMonth(), 1)
|
|
||||||
let dayOfWeek = firstDay.getDay()
|
|
||||||
let startDate = new Date(firstDay)
|
|
||||||
startDate.setDate(startDate.getDate(
|
|
||||||
) - dayOfWeek - 7) // Extra week padding
|
|
||||||
let lastDay = new Date(displayDate.getFullYear(),
|
|
||||||
displayDate.getMonth() + 1, 0)
|
|
||||||
let endDate = new Date(lastDay)
|
|
||||||
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay(
|
|
||||||
)) + 7) // Extra week padding
|
|
||||||
CalendarService.loadEvents(startDate, endDate)
|
CalendarService.loadEvents(startDate, endDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
onDisplayDateChanged: {
|
onDisplayDateChanged: loadEventsForMonth()
|
||||||
loadEventsForMonth()
|
Component.onCompleted: loadEventsForMonth()
|
||||||
}
|
|
||||||
Component.onCompleted: {
|
|
||||||
loadEventsForMonth()
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onKhalAvailableChanged() {
|
function onKhalAvailableChanged() {
|
||||||
if (CalendarService && CalendarService.khalAvailable)
|
if (CalendarService && CalendarService.khalAvailable) {
|
||||||
loadEventsForMonth()
|
loadEventsForMonth()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target: CalendarService
|
target: CalendarService
|
||||||
@@ -55,10 +51,7 @@ Column {
|
|||||||
width: 40
|
width: 40
|
||||||
height: 40
|
height: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
|
color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -96,10 +89,7 @@ Column {
|
|||||||
width: 40
|
width: 40
|
||||||
height: 40
|
height: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
|
color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -129,10 +119,10 @@ Column {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: {
|
model: {
|
||||||
var days = []
|
const days = []
|
||||||
var locale = Qt.locale()
|
const locale = Qt.locale()
|
||||||
for (var i = 0; i < 7; i++) {
|
for (var i = 0; i < 7; i++) {
|
||||||
var date = new Date(2024, 0, 7 + i)
|
const date = new Date(2024, 0, 7 + i)
|
||||||
days.push(locale.dayName(i, Locale.ShortFormat))
|
days.push(locale.dayName(i, Locale.ShortFormat))
|
||||||
}
|
}
|
||||||
return days
|
return days
|
||||||
@@ -147,8 +137,7 @@ Column {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: modelData
|
text: modelData
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
||||||
Theme.surfaceText.b, 0.6)
|
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,10 +145,9 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
property date firstDay: {
|
readonly property date firstDay: {
|
||||||
let date = new Date(displayDate.getFullYear(),
|
const date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
|
||||||
displayDate.getMonth(), 1)
|
const dayOfWeek = date.getDay()
|
||||||
let dayOfWeek = date.getDay()
|
|
||||||
date.setDate(date.getDate() - dayOfWeek)
|
date.setDate(date.getDate() - dayOfWeek)
|
||||||
return date
|
return date
|
||||||
}
|
}
|
||||||
@@ -173,17 +161,14 @@ Column {
|
|||||||
model: 42
|
model: 42
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
property date dayDate: {
|
readonly property date dayDate: {
|
||||||
let date = new Date(parent.firstDay)
|
const date = new Date(parent.firstDay)
|
||||||
date.setDate(date.getDate() + index)
|
date.setDate(date.getDate() + index)
|
||||||
return date
|
return date
|
||||||
}
|
}
|
||||||
property bool isCurrentMonth: dayDate.getMonth(
|
readonly property bool isCurrentMonth: dayDate.getMonth() === displayDate.getMonth()
|
||||||
) === displayDate.getMonth()
|
readonly property bool isToday: dayDate.toDateString() === new Date().toDateString()
|
||||||
property bool isToday: dayDate.toDateString(
|
readonly property bool isSelected: dayDate.toDateString() === selectedDate.toDateString()
|
||||||
) === new Date().toDateString()
|
|
||||||
property bool isSelected: dayDate.toDateString(
|
|
||||||
) === selectedDate.toDateString()
|
|
||||||
|
|
||||||
width: parent.width / 7
|
width: parent.width / 7
|
||||||
height: parent.height / 6
|
height: parent.height / 6
|
||||||
@@ -194,11 +179,7 @@ Column {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: parent.width - 4
|
width: parent.width - 4
|
||||||
height: parent.height - 4
|
height: parent.height - 4
|
||||||
color: isSelected ? Theme.primary : isToday ? Qt.rgba(
|
color: isSelected ? Theme.primary : isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
@@ -207,8 +188,7 @@ Column {
|
|||||||
text: dayDate.getDate()
|
text: dayDate.getDate()
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: isSelected ? Theme.surface : isToday ? Theme.primary : isCurrentMonth ? Theme.surfaceText : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4)
|
color: isSelected ? Theme.surface : isToday ? Theme.primary : isCurrentMonth ? Theme.surfaceText : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4)
|
||||||
font.weight: isToday
|
font.weight: isToday || isSelected ? Font.Medium : Font.Normal
|
||||||
|| isSelected ? Font.Medium : Font.Normal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -216,17 +196,8 @@ Column {
|
|||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
visible: CalendarService
|
visible: CalendarService && CalendarService.khalAvailable && CalendarService.hasEventsForDate(dayDate)
|
||||||
&& CalendarService.khalAvailable
|
opacity: isSelected ? 0.9 : isToday ? 0.8 : 0.6
|
||||||
&& CalendarService.hasEventsForDate(dayDate)
|
|
||||||
opacity: {
|
|
||||||
if (isSelected)
|
|
||||||
return 0.9
|
|
||||||
else if (isToday)
|
|
||||||
return 0.8
|
|
||||||
else
|
|
||||||
return 0.6
|
|
||||||
}
|
|
||||||
|
|
||||||
gradient: Gradient {
|
gradient: Gradient {
|
||||||
GradientStop {
|
GradientStop {
|
||||||
@@ -236,26 +207,12 @@ Column {
|
|||||||
|
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.9
|
position: 0.9
|
||||||
color: {
|
color: isSelected ? Qt.lighter(Theme.primary, 1.3) : Theme.primary
|
||||||
if (isSelected)
|
|
||||||
return Qt.lighter(Theme.primary, 1.3)
|
|
||||||
else if (isToday)
|
|
||||||
return Theme.primary
|
|
||||||
else
|
|
||||||
return Theme.primary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 1
|
position: 1
|
||||||
color: {
|
color: isSelected ? Qt.lighter(Theme.primary, 1.3) : Theme.primary
|
||||||
if (isSelected)
|
|
||||||
return Qt.lighter(Theme.primary, 1.3)
|
|
||||||
else if (isToday)
|
|
||||||
return Theme.primary
|
|
||||||
else
|
|
||||||
return Theme.primary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,9 +231,7 @@ Column {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: selectedDate = dayDate
|
||||||
selectedDate = dayDate
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ PanelWindow {
|
|||||||
closeTimer.stop()
|
closeTimer.stop()
|
||||||
shouldBeVisible = true
|
shouldBeVisible = true
|
||||||
visible = true
|
visible = true
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => calendarGrid.loadEventsForMonth())
|
||||||
calendarGrid.loadEventsForMonth()
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
shouldBeVisible = false
|
shouldBeVisible = false
|
||||||
closeTimer.restart()
|
closeTimer.restart()
|
||||||
@@ -55,8 +53,9 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible && calendarGrid)
|
if (visible && calendarGrid) {
|
||||||
calendarGrid.loadEventsForMonth()
|
calendarGrid.loadEventsForMonth()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
implicitWidth: 480
|
implicitWidth: 480
|
||||||
implicitHeight: 600
|
implicitHeight: 600
|
||||||
@@ -75,32 +74,27 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: mainContainer
|
id: mainContainer
|
||||||
|
|
||||||
readonly property real targetWidth: Math.min(
|
readonly property real targetWidth: Math.min((root.screen ? root.screen.width : Screen.width) * 0.9, 600)
|
||||||
(root.screen ? root.screen.width : Screen.width)
|
|
||||||
* 0.9, 600)
|
|
||||||
|
|
||||||
function calculateWidth() {
|
function calculateWidth() {
|
||||||
let baseWidth = 320
|
const baseWidth = 320
|
||||||
if (leftWidgets.hasAnyWidgets)
|
if (leftWidgets.hasAnyWidgets) {
|
||||||
return Math.min(parent.width * 0.9, 600)
|
return Math.min(parent.width * 0.9, 600)
|
||||||
|
}
|
||||||
return Math.min(parent.width * 0.7, 400)
|
return Math.min(parent.width * 0.7, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateHeight() {
|
function calculateHeight() {
|
||||||
let contentHeight = Theme.spacingM * 2
|
let contentHeight = Theme.spacingM * 2
|
||||||
// margins
|
|
||||||
let widgetHeight = 160
|
let widgetHeight = 160
|
||||||
widgetHeight += 140 + Theme.spacingM
|
widgetHeight += 140 + Theme.spacingM
|
||||||
let calendarHeight = 300
|
const calendarHeight = 300
|
||||||
let mainRowHeight = Math.max(widgetHeight, calendarHeight)
|
const mainRowHeight = Math.max(widgetHeight, calendarHeight)
|
||||||
contentHeight += mainRowHeight + Theme.spacingM
|
contentHeight += mainRowHeight + Theme.spacingM
|
||||||
|
|
||||||
if (CalendarService && CalendarService.khalAvailable) {
|
if (CalendarService && CalendarService.khalAvailable) {
|
||||||
let hasEvents = events.selectedDateEvents
|
const hasEvents = events.selectedDateEvents && events.selectedDateEvents.length > 0
|
||||||
&& events.selectedDateEvents.length > 0
|
const eventsHeight = hasEvents ? Math.min(300, 80 + events.selectedDateEvents.length * 60) : 120
|
||||||
let eventsHeight = hasEvents ? Math.min(
|
|
||||||
300,
|
|
||||||
80 + events.selectedDateEvents.length * 60) : 120
|
|
||||||
contentHeight += eventsHeight
|
contentHeight += eventsHeight
|
||||||
} else {
|
} else {
|
||||||
contentHeight -= Theme.spacingM
|
contentHeight -= Theme.spacingM
|
||||||
@@ -109,26 +103,22 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readonly property real calculatedX: {
|
readonly property real calculatedX: {
|
||||||
var screenWidth = root.screen ? root.screen.width : Screen.width
|
const screenWidth = root.screen ? root.screen.width : Screen.width
|
||||||
if (root.triggerSection === "center") {
|
if (root.triggerSection === "center") {
|
||||||
return (screenWidth - targetWidth) / 2
|
return (screenWidth - targetWidth) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
|
const centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
|
||||||
|
|
||||||
if (centerX >= Theme.spacingM
|
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) {
|
||||||
&& centerX + targetWidth <= screenWidth - Theme.spacingM) {
|
|
||||||
return centerX
|
return centerX
|
||||||
}
|
}
|
||||||
|
|
||||||
if (centerX < Theme.spacingM) {
|
if (centerX < Theme.spacingM) {
|
||||||
return Theme.spacingM
|
return Theme.spacingM
|
||||||
}
|
}
|
||||||
|
|
||||||
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
|
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
|
||||||
return screenWidth - targetWidth - Theme.spacingM
|
return screenWidth - targetWidth - Theme.spacingM
|
||||||
}
|
}
|
||||||
|
|
||||||
return centerX
|
return centerX
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,8 +126,7 @@ PanelWindow {
|
|||||||
height: calculateHeight()
|
height: calculateHeight()
|
||||||
color: Theme.surfaceContainer
|
color: Theme.surfaceContainer
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
opacity: shouldBeVisible ? 1 : 0
|
opacity: shouldBeVisible ? 1 : 0
|
||||||
@@ -145,21 +134,24 @@ PanelWindow {
|
|||||||
x: calculatedX
|
x: calculatedX
|
||||||
y: root.triggerY
|
y: root.triggerY
|
||||||
onOpacityChanged: {
|
onOpacityChanged: {
|
||||||
if (opacity === 1)
|
if (opacity === 1) {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
height = calculateHeight()
|
height = calculateHeight()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onEventsByDateChanged() {
|
function onEventsByDateChanged() {
|
||||||
if (mainContainer.opacity === 1)
|
if (mainContainer.opacity === 1) {
|
||||||
mainContainer.height = mainContainer.calculateHeight()
|
mainContainer.height = mainContainer.calculateHeight()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKhalAvailableChanged() {
|
function onKhalAvailableChanged() {
|
||||||
if (mainContainer.opacity === 1)
|
if (mainContainer.opacity === 1) {
|
||||||
mainContainer.height = mainContainer.calculateHeight()
|
mainContainer.height = mainContainer.calculateHeight()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target: CalendarService
|
target: CalendarService
|
||||||
@@ -168,8 +160,9 @@ PanelWindow {
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onSelectedDateEventsChanged() {
|
function onSelectedDateEventsChanged() {
|
||||||
if (mainContainer.opacity === 1)
|
if (mainContainer.opacity === 1) {
|
||||||
mainContainer.height = mainContainer.calculateHeight()
|
mainContainer.height = mainContainer.calculateHeight()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target: events
|
target: events
|
||||||
@@ -178,8 +171,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
|
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
|
||||||
Theme.surfaceTint.b, 0.04)
|
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
|
|
||||||
SequentialAnimation on opacity {
|
SequentialAnimation on opacity {
|
||||||
@@ -219,10 +211,8 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: {
|
height: {
|
||||||
let widgetHeight = 160
|
let widgetHeight = 160
|
||||||
// Media widget
|
widgetHeight += 140 + Theme.spacingM
|
||||||
widgetHeight += 140 + Theme.spacingM // Weather/SystemInfo widget with spacing
|
const calendarHeight = 300
|
||||||
let calendarHeight = 300
|
|
||||||
// Calendar
|
|
||||||
return Math.max(widgetHeight, calendarHeight)
|
return Math.max(widgetHeight, calendarHeight)
|
||||||
}
|
}
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
@@ -232,8 +222,7 @@ PanelWindow {
|
|||||||
|
|
||||||
property bool hasAnyWidgets: true
|
property bool hasAnyWidgets: true
|
||||||
|
|
||||||
width: hasAnyWidgets ? parent.width
|
width: hasAnyWidgets ? parent.width * 0.42 : 0
|
||||||
* 0.42 : 0 // Slightly narrower for better proportions
|
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
visible: hasAnyWidgets
|
visible: hasAnyWidgets
|
||||||
@@ -258,15 +247,11 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width
|
width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width - Theme.spacingM : parent.width
|
||||||
- Theme.spacingM : parent.width
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceVariant.r,
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
|
||||||
Theme.surfaceVariant.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
Theme.surfaceVariant.b, 0.2)
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
CalendarGrid {
|
CalendarGrid {
|
||||||
@@ -317,10 +302,10 @@ PanelWindow {
|
|||||||
z: -1
|
z: -1
|
||||||
enabled: shouldBeVisible
|
enabled: shouldBeVisible
|
||||||
onClicked: function (mouse) {
|
onClicked: function (mouse) {
|
||||||
var localPos = mapToItem(mainContainer, mouse.x, mouse.y)
|
const localPos = mapToItem(mainContainer, mouse.x, mouse.y)
|
||||||
if (localPos.x < 0 || localPos.x > mainContainer.width
|
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0 || localPos.y > mainContainer.height) {
|
||||||
|| localPos.y < 0 || localPos.y > mainContainer.height)
|
|
||||||
calendarVisible = false
|
calendarVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Rectangle {
|
|||||||
|
|
||||||
function updateSelectedDateEvents() {
|
function updateSelectedDateEvents() {
|
||||||
if (CalendarService && CalendarService.khalAvailable) {
|
if (CalendarService && CalendarService.khalAvailable) {
|
||||||
let events = CalendarService.getEventsForDate(selectedDate)
|
const events = CalendarService.getEventsForDate(selectedDate)
|
||||||
selectedDateEvents = events
|
selectedDateEvents = events
|
||||||
} else {
|
} else {
|
||||||
selectedDateEvents = []
|
selectedDateEvents = []
|
||||||
@@ -25,23 +25,15 @@ Rectangle {
|
|||||||
eventsList.model = selectedDateEvents
|
eventsList.model = selectedDateEvents
|
||||||
}
|
}
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: shouldShow ? (hasEvents ? Math.min(
|
height: shouldShow ? (hasEvents ? Math.min(300, 80 + selectedDateEvents.length * 60) : 120) : 0
|
||||||
300,
|
|
||||||
80 + selectedDateEvents.length * 60) : 120) : 0
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12)
|
||||||
Theme.surfaceVariant.b, 0.12)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
visible: shouldShow
|
visible: shouldShow
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
Component.onCompleted: {
|
Component.onCompleted: updateSelectedDateEvents()
|
||||||
updateSelectedDateEvents()
|
onSelectedDateChanged: updateSelectedDateEvents()
|
||||||
}
|
|
||||||
onSelectedDateChanged: {
|
|
||||||
updateSelectedDateEvents()
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onEventsByDateChanged() {
|
function onEventsByDateChanged() {
|
||||||
@@ -73,11 +65,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: hasEvents ? (Qt.formatDate(selectedDate, "MMM d") + " • "
|
text: hasEvents ? (Qt.formatDate(selectedDate, "MMM d") + " • " + (selectedDateEvents.length === 1 ? "1 event" : selectedDateEvents.length + " events")) : Qt.formatDate(selectedDate, "MMM d")
|
||||||
+ (selectedDateEvents.length
|
|
||||||
=== 1 ? "1 event" : selectedDateEvents.length
|
|
||||||
+ " events")) : Qt.formatDate(
|
|
||||||
selectedDate, "MMM d")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -93,16 +81,14 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: "event_busy"
|
name: "event_busy"
|
||||||
size: Theme.iconSize + 8
|
size: Theme.iconSize + 8
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||||
Theme.surfaceText.b, 0.3)
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No events"
|
text: "No events"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||||
Theme.surfaceText.b, 0.5)
|
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
@@ -123,7 +109,6 @@ Rectangle {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
|
||||||
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
|
|
||||||
interactive: true
|
interactive: true
|
||||||
flickDeceleration: 1500
|
flickDeceleration: 1500
|
||||||
maximumFlickVelocity: 2000
|
maximumFlickVelocity: 2000
|
||||||
@@ -131,26 +116,20 @@ Rectangle {
|
|||||||
pressDelay: 0
|
pressDelay: 0
|
||||||
flickableDirection: Flickable.VerticalFlick
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
|
||||||
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
|
|
||||||
WheelHandler {
|
WheelHandler {
|
||||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
||||||
property real momentum: 0
|
property real momentum: 0
|
||||||
onWheel: event => {
|
onWheel: event => {
|
||||||
if (event.pixelDelta.y !== 0) {
|
if (event.pixelDelta.y !== 0) {
|
||||||
// Touchpad with pixel delta
|
|
||||||
momentum = event.pixelDelta.y * 1.8
|
momentum = event.pixelDelta.y * 1.8
|
||||||
} else {
|
} else {
|
||||||
// Mouse wheel with angle delta
|
momentum = (event.angleDelta.y / 120) * (60 * 2.5)
|
||||||
momentum = (event.angleDelta.y / 120)
|
|
||||||
* (60 * 2.5) // ~2.5 items per wheel step
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let newY = parent.contentY - momentum
|
let newY = parent.contentY - momentum
|
||||||
newY = Math.max(
|
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
|
||||||
0, Math.min(parent.contentHeight - parent.height,
|
|
||||||
newY))
|
|
||||||
parent.contentY = newY
|
parent.contentY = newY
|
||||||
momentum *= 0.92 // Decay for smooth momentum
|
momentum *= 0.92
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,22 +146,19 @@ Rectangle {
|
|||||||
height: eventContent.implicitHeight + Theme.spacingM
|
height: eventContent.implicitHeight + Theme.spacingM
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: {
|
color: {
|
||||||
if (modelData.url && eventMouseArea.containsMouse)
|
if (modelData.url && eventMouseArea.containsMouse) {
|
||||||
return Qt.rgba(Theme.primary.r, Theme.primary.g,
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||||
Theme.primary.b, 0.12)
|
} else if (eventMouseArea.containsMouse) {
|
||||||
else if (eventMouseArea.containsMouse)
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06)
|
||||||
return Qt.rgba(Theme.primary.r, Theme.primary.g,
|
}
|
||||||
Theme.primary.b, 0.06)
|
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.06)
|
||||||
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b, 0.06)
|
|
||||||
}
|
}
|
||||||
border.color: {
|
border.color: {
|
||||||
if (modelData.url && eventMouseArea.containsMouse)
|
if (modelData.url && eventMouseArea.containsMouse) {
|
||||||
return Qt.rgba(Theme.primary.r, Theme.primary.g,
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
|
||||||
Theme.primary.b, 0.3)
|
} else if (eventMouseArea.containsMouse) {
|
||||||
else if (eventMouseArea.containsMouse)
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15)
|
||||||
return Qt.rgba(Theme.primary.r, Theme.primary.g,
|
}
|
||||||
Theme.primary.b, 0.15)
|
|
||||||
return "transparent"
|
return "transparent"
|
||||||
}
|
}
|
||||||
border.width: 1
|
border.width: 1
|
||||||
@@ -233,9 +209,7 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: "schedule"
|
name: "schedule"
|
||||||
size: Theme.fontSizeSmall
|
size: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,23 +218,16 @@ Rectangle {
|
|||||||
if (modelData.allDay) {
|
if (modelData.allDay) {
|
||||||
return "All day"
|
return "All day"
|
||||||
} else {
|
} else {
|
||||||
let timeFormat = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
const timeFormat = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
||||||
let startTime = Qt.formatTime(
|
const startTime = Qt.formatTime(modelData.start, timeFormat)
|
||||||
modelData.start, timeFormat)
|
if (modelData.start.toDateString() !== modelData.end.toDateString() || modelData.start.getTime() !== modelData.end.getTime()) {
|
||||||
if (modelData.start.toDateString(
|
return startTime + " – " + Qt.formatTime(modelData.end, timeFormat)
|
||||||
) !== modelData.end.toDateString(
|
}
|
||||||
) || modelData.start.getTime(
|
|
||||||
) !== modelData.end.getTime())
|
|
||||||
return startTime + " – " + Qt.formatTime(
|
|
||||||
modelData.end, timeFormat)
|
|
||||||
|
|
||||||
return startTime
|
return startTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
@@ -277,18 +244,14 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: "location_on"
|
name: "location_on"
|
||||||
size: Theme.fontSizeSmall
|
size: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: modelData.location
|
text: modelData.location
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
@@ -307,8 +270,9 @@ Rectangle {
|
|||||||
enabled: modelData.url !== ""
|
enabled: modelData.url !== ""
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData.url && modelData.url !== "") {
|
if (modelData.url && modelData.url !== "") {
|
||||||
if (Qt.openUrlExternally(modelData.url) === false)
|
if (Qt.openUrlExternally(modelData.url) === false) {
|
||||||
console.warn("Failed to open URL: " + modelData.url)
|
console.warn("Failed to open URL: " + modelData.url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,30 +15,27 @@ Rectangle {
|
|||||||
property string lastValidArtist: ""
|
property string lastValidArtist: ""
|
||||||
property string lastValidAlbum: ""
|
property string lastValidAlbum: ""
|
||||||
property string lastValidArtUrl: ""
|
property string lastValidArtUrl: ""
|
||||||
property real currentPosition: activePlayer
|
property real currentPosition: activePlayer && activePlayer.positionSupported ? activePlayer.position : 0
|
||||||
&& activePlayer.positionSupported ? activePlayer.position : 0
|
|
||||||
property real displayPosition: currentPosition
|
property real displayPosition: currentPosition
|
||||||
|
|
||||||
function ratio() {
|
readonly property real ratio: {
|
||||||
if (!activePlayer || activePlayer.length <= 0) {
|
if (!activePlayer || activePlayer.length <= 0) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
let calculatedRatio = displayPosition / activePlayer.length
|
const calculatedRatio = displayPosition / activePlayer.length
|
||||||
return Math.max(0, Math.min(1, calculatedRatio))
|
return Math.max(0, Math.min(1, calculatedRatio))
|
||||||
}
|
}
|
||||||
|
|
||||||
onActivePlayerChanged: {
|
onActivePlayerChanged: {
|
||||||
if (activePlayer && activePlayer.positionSupported) {
|
if (activePlayer && activePlayer.positionSupported) {
|
||||||
currentPosition = Qt.binding(() => activePlayer.position)
|
currentPosition = Qt.binding(() => activePlayer?.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: positionTimer
|
id: positionTimer
|
||||||
interval: 300
|
interval: 300
|
||||||
running: activePlayer
|
running: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing && !progressMouseArea.isSeeking
|
||||||
&& activePlayer.playbackState === MprisPlaybackState.Playing
|
|
||||||
&& !progressMouseArea.isSeeking
|
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: activePlayer && activePlayer.positionSupported && activePlayer.positionChanged()
|
onTriggered: activePlayer && activePlayer.positionSupported && activePlayer.positionChanged()
|
||||||
}
|
}
|
||||||
@@ -46,14 +43,11 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
|
||||||
Theme.surfaceContainer.b, 0.4)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: cleanupTimer
|
id: cleanupTimer
|
||||||
|
|
||||||
@@ -69,7 +63,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingS
|
anchors.margins: Theme.spacingS
|
||||||
@@ -77,23 +70,19 @@ Rectangle {
|
|||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: (!activePlayer && !lastValidTitle)
|
visible: (!activePlayer && !lastValidTitle) || (activePlayer && activePlayer.trackTitle === "" && lastValidTitle === "")
|
||||||
|| (activePlayer && activePlayer.trackTitle === ""
|
|
||||||
&& lastValidTitle === "")
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "music_note"
|
name: "music_note"
|
||||||
size: Theme.iconSize + 8
|
size: Theme.iconSize + 8
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||||
Theme.surfaceText.b, 0.5)
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No Media Playing"
|
text: "No Media Playing"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,8 +90,7 @@ Rectangle {
|
|||||||
Column {
|
Column {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: activePlayer && activePlayer.trackTitle !== ""
|
visible: (activePlayer && activePlayer.trackTitle !== "") || lastValidTitle !== ""
|
||||||
|| lastValidTitle !== ""
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -113,9 +101,7 @@ Rectangle {
|
|||||||
width: 60
|
width: 60
|
||||||
height: 60
|
height: 60
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceVariant.r,
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b, 0.3)
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -125,12 +111,11 @@ Rectangle {
|
|||||||
id: albumArt
|
id: albumArt
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: activePlayer && activePlayer.trackArtUrl
|
source: (activePlayer && activePlayer.trackArtUrl) || lastValidArtUrl || ""
|
||||||
|| lastValidArtUrl || ""
|
|
||||||
onSourceChanged: {
|
onSourceChanged: {
|
||||||
if (activePlayer && activePlayer.trackArtUrl
|
if (activePlayer && activePlayer.trackArtUrl && albumArt.status !== Image.Error) {
|
||||||
&& albumArt.status !== Image.Error)
|
|
||||||
lastValidArtUrl = activePlayer.trackArtUrl
|
lastValidArtUrl = activePlayer.trackArtUrl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
smooth: true
|
smooth: true
|
||||||
@@ -168,11 +153,11 @@ Rectangle {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: activePlayer && activePlayer.trackTitle
|
text: (activePlayer && activePlayer.trackTitle) || lastValidTitle || "Unknown Track"
|
||||||
|| lastValidTitle || "Unknown Track"
|
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (activePlayer && activePlayer.trackTitle)
|
if (activePlayer && activePlayer.trackTitle) {
|
||||||
lastValidTitle = activePlayer.trackTitle
|
lastValidTitle = activePlayer.trackTitle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
@@ -184,16 +169,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: activePlayer && activePlayer.trackArtist
|
text: (activePlayer && activePlayer.trackArtist) || lastValidArtist || "Unknown Artist"
|
||||||
|| lastValidArtist || "Unknown Artist"
|
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (activePlayer && activePlayer.trackArtist)
|
if (activePlayer && activePlayer.trackArtist) {
|
||||||
lastValidArtist = activePlayer.trackArtist
|
lastValidArtist = activePlayer.trackArtist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.8)
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
@@ -201,16 +184,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: activePlayer && activePlayer.trackAlbum
|
text: (activePlayer && activePlayer.trackAlbum) || lastValidAlbum || ""
|
||||||
|| lastValidAlbum || ""
|
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (activePlayer && activePlayer.trackAlbum)
|
if (activePlayer && activePlayer.trackAlbum) {
|
||||||
lastValidAlbum = activePlayer.trackAlbum
|
lastValidAlbum = activePlayer.trackAlbum
|
||||||
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.6)
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
@@ -232,9 +213,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 6
|
height: 6
|
||||||
radius: 3
|
radius: 3
|
||||||
color: Qt.rgba(Theme.surfaceVariant.r,
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b, 0.3)
|
|
||||||
visible: activePlayer !== null
|
visible: activePlayer !== null
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
@@ -244,8 +223,7 @@ Rectangle {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
width: Math.max(0, Math.min(parent.width,
|
width: Math.max(0, Math.min(parent.width, parent.width * ratio))
|
||||||
parent.width * ratio()))
|
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -263,12 +241,10 @@ Rectangle {
|
|||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
border.color: Qt.lighter(Theme.primary, 1.3)
|
border.color: Qt.lighter(Theme.primary, 1.3)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
x: Math.max(0, Math.min(parent.width - width,
|
x: Math.max(0, Math.min(parent.width - width, progressFill.width - width / 2))
|
||||||
progressFill.width - width / 2))
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: activePlayer && activePlayer.length > 0
|
visible: activePlayer && activePlayer.length > 0
|
||||||
scale: progressMouseArea.containsMouse
|
scale: progressMouseArea.containsMouse || progressMouseArea.pressed ? 1.2 : 1
|
||||||
|| progressMouseArea.pressed ? 1.2 : 1
|
|
||||||
|
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -290,66 +266,51 @@ Rectangle {
|
|||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (progressMouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
if (progressMouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
||||||
let clampedPosition = Math.min(progressMouseArea.pendingSeekPosition, activePlayer.length * 0.99)
|
const clampedPosition = Math.min(progressMouseArea.pendingSeekPosition, activePlayer.length * 0.99)
|
||||||
activePlayer.position = clampedPosition
|
activePlayer.position = clampedPosition
|
||||||
progressMouseArea.pendingSeekPosition = -1
|
progressMouseArea.pendingSeekPosition = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
enabled: activePlayer && activePlayer.length > 0
|
enabled: activePlayer && activePlayer.length > 0 && activePlayer.canSeek
|
||||||
&& activePlayer.canSeek
|
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
onPressed: function (mouse) {
|
onPressed: mouse => {
|
||||||
isSeeking = true
|
isSeeking = true
|
||||||
if (activePlayer && activePlayer.length > 0
|
if (activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
|
||||||
&& activePlayer.canSeek) {
|
const ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width))
|
||||||
let ratio = Math.max(
|
pendingSeekPosition = ratio * activePlayer.length
|
||||||
0, Math.min(
|
displayPosition = pendingSeekPosition
|
||||||
1,
|
seekDebounceTimer.restart()
|
||||||
mouse.x / progressBarBackground.width))
|
}
|
||||||
pendingSeekPosition = ratio * activePlayer.length
|
}
|
||||||
displayPosition = pendingSeekPosition
|
|
||||||
seekDebounceTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
isSeeking = false
|
isSeeking = false
|
||||||
seekDebounceTimer.stop()
|
seekDebounceTimer.stop()
|
||||||
if (pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
if (pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
||||||
let clampedPosition = Math.min(pendingSeekPosition, activePlayer.length * 0.99)
|
const clampedPosition = Math.min(pendingSeekPosition, activePlayer.length * 0.99)
|
||||||
activePlayer.position = clampedPosition
|
activePlayer.position = clampedPosition
|
||||||
pendingSeekPosition = -1
|
pendingSeekPosition = -1
|
||||||
}
|
}
|
||||||
displayPosition = Qt.binding(() => currentPosition)
|
displayPosition = Qt.binding(() => currentPosition)
|
||||||
}
|
}
|
||||||
onPositionChanged: function (mouse) {
|
onPositionChanged: mouse => {
|
||||||
if (pressed && isSeeking && activePlayer
|
if (pressed && isSeeking && activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
|
||||||
&& activePlayer.length > 0
|
const ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width))
|
||||||
&& activePlayer.canSeek) {
|
pendingSeekPosition = ratio * activePlayer.length
|
||||||
let ratio = Math.max(
|
displayPosition = pendingSeekPosition
|
||||||
0, Math.min(
|
seekDebounceTimer.restart()
|
||||||
1,
|
}
|
||||||
mouse.x / progressBarBackground.width))
|
}
|
||||||
pendingSeekPosition = ratio * activePlayer.length
|
onClicked: mouse => {
|
||||||
displayPosition = pendingSeekPosition
|
if (activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
|
||||||
seekDebounceTimer.restart()
|
const ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width))
|
||||||
}
|
activePlayer.position = ratio * activePlayer.length
|
||||||
}
|
}
|
||||||
onClicked: function (mouse) {
|
}
|
||||||
if (activePlayer && activePlayer.length > 0
|
|
||||||
&& activePlayer.canSeek) {
|
|
||||||
let ratio = Math.max(
|
|
||||||
0, Math.min(
|
|
||||||
1,
|
|
||||||
mouse.x / progressBarBackground.width))
|
|
||||||
activePlayer.position = ratio * activePlayer.length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -362,26 +323,20 @@ Rectangle {
|
|||||||
enabled: progressMouseArea.isSeeking
|
enabled: progressMouseArea.isSeeking
|
||||||
visible: false
|
visible: false
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
onPositionChanged: function (mouse) {
|
onPositionChanged: mouse => {
|
||||||
if (progressMouseArea.isSeeking && activePlayer
|
if (progressMouseArea.isSeeking && activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
|
||||||
&& activePlayer.length > 0
|
const globalPos = mapToItem(progressBarBackground, mouse.x, mouse.y)
|
||||||
&& activePlayer.canSeek) {
|
const ratio = Math.max(0, Math.min(1, globalPos.x / progressBarBackground.width))
|
||||||
let globalPos = mapToItem(progressBarBackground,
|
progressMouseArea.pendingSeekPosition = ratio * activePlayer.length
|
||||||
mouse.x, mouse.y)
|
displayPosition = progressMouseArea.pendingSeekPosition
|
||||||
let ratio = Math.max(
|
seekDebounceTimer.restart()
|
||||||
0, Math.min(
|
}
|
||||||
1,
|
}
|
||||||
globalPos.x / progressBarBackground.width))
|
|
||||||
progressMouseArea.pendingSeekPosition = ratio * activePlayer.length
|
|
||||||
displayPosition = progressMouseArea.pendingSeekPosition
|
|
||||||
seekDebounceTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
progressMouseArea.isSeeking = false
|
progressMouseArea.isSeeking = false
|
||||||
seekDebounceTimer.stop()
|
seekDebounceTimer.stop()
|
||||||
if (progressMouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
if (progressMouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
|
||||||
let clampedPosition = Math.min(progressMouseArea.pendingSeekPosition, activePlayer.length * 0.99)
|
const clampedPosition = Math.min(progressMouseArea.pendingSeekPosition, activePlayer.length * 0.99)
|
||||||
activePlayer.position = clampedPosition
|
activePlayer.position = clampedPosition
|
||||||
progressMouseArea.pendingSeekPosition = -1
|
progressMouseArea.pendingSeekPosition = -1
|
||||||
}
|
}
|
||||||
@@ -404,11 +359,7 @@ Rectangle {
|
|||||||
width: 28
|
width: 28
|
||||||
height: 28
|
height: 28
|
||||||
radius: 14
|
radius: 14
|
||||||
color: prevBtnArea.containsMouse ? Qt.rgba(
|
color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"
|
||||||
Theme.surfaceVariant.r,
|
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -424,11 +375,11 @@ Rectangle {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!activePlayer)
|
if (!activePlayer) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (activePlayer.position > 8
|
if (activePlayer.position > 8 && activePlayer.canSeek) {
|
||||||
&& activePlayer.canSeek) {
|
|
||||||
activePlayer.position = 0
|
activePlayer.position = 0
|
||||||
} else {
|
} else {
|
||||||
activePlayer.previous()
|
activePlayer.previous()
|
||||||
@@ -445,8 +396,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: activePlayer && activePlayer.playbackState
|
name: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
|
||||||
=== MprisPlaybackState.Playing ? "pause" : "play_arrow"
|
|
||||||
size: 20
|
size: 20
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
}
|
}
|
||||||
@@ -455,8 +405,7 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: activePlayer
|
onClicked: activePlayer && activePlayer.togglePlaying()
|
||||||
&& activePlayer.togglePlaying()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,11 +413,7 @@ Rectangle {
|
|||||||
width: 28
|
width: 28
|
||||||
height: 28
|
height: 28
|
||||||
radius: 14
|
radius: 14
|
||||||
color: nextBtnArea.containsMouse ? Qt.rgba(
|
color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"
|
||||||
Theme.surfaceVariant.r,
|
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ Rectangle {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
|
||||||
Theme.surfaceContainer.b, 0.4)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
Ref {
|
Component.onCompleted: {
|
||||||
service: DgopService
|
DgopService.addRef(["system", "hardware"])
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
DgopService.removeRef(["system", "hardware"])
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -48,8 +49,7 @@ Rectangle {
|
|||||||
StyledText {
|
StyledText {
|
||||||
text: DgopService.distribution + " • " + DgopService.architecture
|
text: DgopService.distribution + " • " + DgopService.architecture
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
@@ -59,8 +59,7 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
|
||||||
Theme.outline.b, 0.1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -86,8 +85,7 @@ Rectangle {
|
|||||||
StyledText {
|
StyledText {
|
||||||
text: DgopService.processCount + " proc, " + DgopService.threadCount + " threads"
|
text: DgopService.processCount + " proc, " + DgopService.threadCount + " threads"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
|
||||||
Theme.surfaceText.b, 0.8)
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
@@ -95,43 +93,36 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatUptime(uptime) {
|
function formatUptime(uptime) {
|
||||||
if (!uptime)
|
if (!uptime) {
|
||||||
return "0m"
|
return "0m"
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the uptime string - handle formats like "1 week, 4 days, 3:45" or "4 days, 3:45" or "3:45"
|
const uptimeStr = uptime.toString().trim()
|
||||||
var uptimeStr = uptime.toString().trim()
|
const weekMatch = uptimeStr.match(/(\d+)\s+weeks?/)
|
||||||
|
const dayMatch = uptimeStr.match(/(\d+)\s+days?/)
|
||||||
// Check for weeks and days - need to add them together
|
|
||||||
var weekMatch = uptimeStr.match(/(\d+)\s+weeks?/)
|
|
||||||
var dayMatch = uptimeStr.match(/(\d+)\s+days?/)
|
|
||||||
|
|
||||||
if (weekMatch) {
|
if (weekMatch) {
|
||||||
var weeks = parseInt(weekMatch[1])
|
const weeks = parseInt(weekMatch[1])
|
||||||
var totalDays = weeks * 7
|
let totalDays = weeks * 7
|
||||||
if (dayMatch) {
|
if (dayMatch) {
|
||||||
var days = parseInt(dayMatch[1])
|
const days = parseInt(dayMatch[1])
|
||||||
totalDays += days
|
totalDays += days
|
||||||
}
|
}
|
||||||
return totalDays + "d"
|
return totalDays + "d"
|
||||||
} else if (dayMatch) {
|
}
|
||||||
var days = parseInt(dayMatch[1])
|
|
||||||
|
if (dayMatch) {
|
||||||
|
const days = parseInt(dayMatch[1])
|
||||||
return days + "d"
|
return days + "d"
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's just hours:minutes, show the largest unit
|
const timeMatch = uptimeStr.match(/(\d+):(\d+)/)
|
||||||
var timeMatch = uptimeStr.match(/(\d+):(\d+)/)
|
|
||||||
if (timeMatch) {
|
if (timeMatch) {
|
||||||
var hours = parseInt(timeMatch[1])
|
const hours = parseInt(timeMatch[1])
|
||||||
var minutes = parseInt(timeMatch[2])
|
const minutes = parseInt(timeMatch[2])
|
||||||
if (hours > 0) {
|
return hours > 0 ? hours + "h" : minutes + "m"
|
||||||
return hours + "h"
|
|
||||||
} else {
|
|
||||||
return minutes + "m"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback - return as is but truncated
|
return uptimeStr.length > 8 ? uptimeStr.substring(0, 8) + "…" : uptimeStr
|
||||||
return uptimeStr.length > 8 ? uptimeStr.substring(0,
|
|
||||||
8) + "…" : uptimeStr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,8 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
|
||||||
Theme.surfaceContainer.b, 0.4)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
|
||||||
@@ -25,22 +23,19 @@ Rectangle {
|
|||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: !WeatherService.weather.available
|
visible: !WeatherService.weather.available || WeatherService.weather.temp === 0
|
||||||
|| WeatherService.weather.temp === 0
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "cloud_off"
|
name: "cloud_off"
|
||||||
size: Theme.iconSize + 8
|
size: Theme.iconSize + 8
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||||
Theme.surfaceText.b, 0.5)
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No Weather Data"
|
text: "No Weather Data"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,8 +44,7 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingL
|
anchors.margins: Theme.spacingL
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: WeatherService.weather.available
|
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0
|
||||||
&& WeatherService.weather.temp !== 0
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -60,8 +54,7 @@ Rectangle {
|
|||||||
id: refreshButton
|
id: refreshButton
|
||||||
name: "refresh"
|
name: "refresh"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.iconSize - 6
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||||
Theme.surfaceText.b, 0.3)
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.rightMargin: -Theme.spacingS
|
anchors.rightMargin: -Theme.spacingS
|
||||||
@@ -102,8 +95,7 @@ Rectangle {
|
|||||||
spacing: Theme.spacingL
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: WeatherService.getWeatherIcon(
|
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||||
WeatherService.weather.wCode)
|
|
||||||
size: Theme.iconSize + 8
|
size: Theme.iconSize + 8
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -114,8 +106,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)
|
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||||
+ "°" + (SettingsData.useFahrenheit ? "F" : "C")
|
|
||||||
font.pixelSize: Theme.fontSizeXLarge
|
font.pixelSize: Theme.fontSizeXLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Light
|
font.weight: Font.Light
|
||||||
@@ -125,9 +116,9 @@ Rectangle {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (WeatherService.weather.available)
|
if (WeatherService.weather.available) {
|
||||||
SettingsData.setTemperatureUnit(
|
SettingsData.setTemperatureUnit(!SettingsData.useFahrenheit)
|
||||||
!SettingsData.useFahrenheit)
|
}
|
||||||
}
|
}
|
||||||
enabled: WeatherService.weather.available
|
enabled: WeatherService.weather.available
|
||||||
}
|
}
|
||||||
@@ -136,9 +127,7 @@ Rectangle {
|
|||||||
StyledText {
|
StyledText {
|
||||||
text: WeatherService.weather.city || ""
|
text: WeatherService.weather.city || ""
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r,
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
Theme.surfaceText.g,
|
|
||||||
Theme.surfaceText.b, 0.7)
|
|
||||||
visible: text.length > 0
|
visible: text.length > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,8 +150,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: WeatherService.weather.humidity ? WeatherService.weather.humidity
|
text: WeatherService.weather.humidity ? WeatherService.weather.humidity + "%" : "--"
|
||||||
+ "%" : "--"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -19,20 +19,16 @@ PanelWindow {
|
|||||||
property bool autoHide: SettingsData.dockAutoHide
|
property bool autoHide: SettingsData.dockAutoHide
|
||||||
property real backgroundTransparency: SettingsData.dockTransparency
|
property real backgroundTransparency: SettingsData.dockTransparency
|
||||||
|
|
||||||
property bool contextMenuOpen: (contextMenu && contextMenu.visible
|
property bool contextMenuOpen: (contextMenu && contextMenu.visible && contextMenu.screen === modelData)
|
||||||
&& contextMenu.screen === modelData)
|
|
||||||
property bool windowIsFullscreen: {
|
property bool windowIsFullscreen: {
|
||||||
if (!ToplevelManager.activeToplevel)
|
if (!ToplevelManager.activeToplevel) {
|
||||||
return false
|
return false
|
||||||
var activeWindow = ToplevelManager.activeToplevel
|
}
|
||||||
var fullscreenApps = ["vlc", "mpv", "kodi", "steam", "lutris", "wine", "dosbox"]
|
const activeWindow = ToplevelManager.activeToplevel
|
||||||
return fullscreenApps.some(app => activeWindow.appId
|
const fullscreenApps = ["vlc", "mpv", "kodi", "steam", "lutris", "wine", "dosbox"]
|
||||||
&& activeWindow.appId.toLowerCase(
|
return fullscreenApps.some(app => activeWindow.appId && activeWindow.appId.toLowerCase().includes(app))
|
||||||
).includes(app))
|
|
||||||
}
|
}
|
||||||
property bool reveal: (!autoHide || dockMouseArea.containsMouse
|
property bool reveal: (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen) && !windowIsFullscreen
|
||||||
|| dockApps.requestDockShow || contextMenuOpen)
|
|
||||||
&& !windowIsFullscreen
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
@@ -68,7 +64,7 @@ PanelWindow {
|
|||||||
property real currentScreen: modelData ? modelData : dock.screen
|
property real currentScreen: modelData ? modelData : dock.screen
|
||||||
property real screenWidth: currentScreen ? currentScreen.geometry.width : 1920
|
property real screenWidth: currentScreen ? currentScreen.geometry.width : 1920
|
||||||
property real maxDockWidth: Math.min(screenWidth * 0.8, 1200)
|
property real maxDockWidth: Math.min(screenWidth * 0.8, 1200)
|
||||||
|
|
||||||
height: dock.reveal ? 65 : 20
|
height: dock.reveal ? 65 : 20
|
||||||
width: dock.reveal ? Math.min(dockBackground.width + 32, maxDockWidth) : Math.min(Math.max(dockBackground.width + 64, 200), screenWidth * 0.5)
|
width: dock.reveal ? Math.min(dockBackground.width + 32, maxDockWidth) : Math.min(Math.max(dockBackground.width + 64, 200), screenWidth * 0.5)
|
||||||
anchors {
|
anchors {
|
||||||
@@ -115,9 +111,7 @@ PanelWindow {
|
|||||||
anchors.topMargin: 4
|
anchors.topMargin: 4
|
||||||
anchors.bottomMargin: 1
|
anchors.bottomMargin: 1
|
||||||
|
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
|
||||||
Theme.surfaceContainer.g,
|
|
||||||
Theme.surfaceContainer.b, backgroundTransparency)
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: Theme.outlineMedium
|
border.color: Theme.outlineMedium
|
||||||
@@ -125,8 +119,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
|
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
|
||||||
Theme.surfaceTint.b, 0.04)
|
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,24 +140,24 @@ PanelWindow {
|
|||||||
id: appTooltip
|
id: appTooltip
|
||||||
|
|
||||||
property var hoveredButton: {
|
property var hoveredButton: {
|
||||||
if (!dockApps.children[0])
|
if (!dockApps.children[0]) {
|
||||||
return null
|
return null
|
||||||
var row = dockApps.children[0]
|
}
|
||||||
var repeater = null
|
const row = dockApps.children[0]
|
||||||
|
let repeater = null
|
||||||
for (var i = 0; i < row.children.length; i++) {
|
for (var i = 0; i < row.children.length; i++) {
|
||||||
var child = row.children[i]
|
const child = row.children[i]
|
||||||
if (child && typeof child.count !== "undefined"
|
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") {
|
||||||
&& typeof child.itemAt === "function") {
|
|
||||||
repeater = child
|
repeater = child
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!repeater || !repeater.itemAt)
|
if (!repeater || !repeater.itemAt) {
|
||||||
return null
|
return null
|
||||||
|
}
|
||||||
for (var i = 0; i < repeater.count; i++) {
|
for (var i = 0; i < repeater.count; i++) {
|
||||||
var item = repeater.itemAt(i)
|
const item = repeater.itemAt(i)
|
||||||
if (item && item.dockButton
|
if (item && item.dockButton && item.dockButton.showTooltip) {
|
||||||
&& item.dockButton.showTooltip) {
|
|
||||||
return item.dockButton
|
return item.dockButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,9 +176,7 @@ PanelWindow {
|
|||||||
border.color: Theme.outlineMedium
|
border.color: Theme.outlineMedium
|
||||||
|
|
||||||
y: -height - 8
|
y: -height - 8
|
||||||
x: hoveredButton ? hoveredButton.mapToItem(
|
x: hoveredButton ? hoveredButton.mapToItem(dockContainer, hoveredButton.width / 2, 0).x - width / 2 : 0
|
||||||
dockContainer, hoveredButton.width / 2,
|
|
||||||
0).x - width / 2 : 0
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: tooltipLabel
|
id: tooltipLabel
|
||||||
|
|||||||
@@ -28,49 +28,48 @@ Item {
|
|||||||
if (!appData || appData.type !== "window") {
|
if (!appData || appData.type !== "window") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var toplevel = getToplevelObject()
|
const toplevel = getToplevelObject()
|
||||||
if (!toplevel) {
|
if (!toplevel) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return toplevel.activated
|
return toplevel.activated
|
||||||
}
|
}
|
||||||
property string tooltipText: {
|
property string tooltipText: {
|
||||||
if (!appData)
|
if (!appData) {
|
||||||
return ""
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// For window type, show app name + window title
|
|
||||||
if (appData.type === "window" && showWindowTitle) {
|
if (appData.type === "window" && showWindowTitle) {
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
||||||
var appName = desktopEntry
|
const appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId
|
||||||
&& desktopEntry.name ? desktopEntry.name : appData.appId
|
|
||||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||||
}
|
}
|
||||||
// For pinned apps, just show app name
|
|
||||||
if (!appData.appId)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
if (!appData.appId) {
|
||||||
return desktopEntry
|
return ""
|
||||||
&& desktopEntry.name ? desktopEntry.name : appData.appId
|
}
|
||||||
|
|
||||||
|
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
||||||
|
return desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 40
|
width: 40
|
||||||
height: 40
|
height: 40
|
||||||
|
|
||||||
function getToplevelObject() {
|
function getToplevelObject() {
|
||||||
if (!appData || appData.type !== "window") {
|
if (!appData || appData.type !== "window") {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
var sortedToplevels = CompositorService.sortedToplevels
|
const sortedToplevels = CompositorService.sortedToplevels
|
||||||
if (!sortedToplevels) {
|
if (!sortedToplevels) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appData.uniqueId) {
|
if (appData.uniqueId) {
|
||||||
for (var i = 0; i < sortedToplevels.length; i++) {
|
for (var i = 0; i < sortedToplevels.length; i++) {
|
||||||
var toplevel = sortedToplevels[i]
|
const toplevel = sortedToplevels[i]
|
||||||
var checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
|
const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
|
||||||
if (checkId === appData.uniqueId) {
|
if (checkId === appData.uniqueId) {
|
||||||
return toplevel
|
return toplevel
|
||||||
}
|
}
|
||||||
@@ -82,7 +81,7 @@ Item {
|
|||||||
return sortedToplevels[appData.windowId]
|
return sortedToplevels[appData.windowId]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
onIsHoveredChanged: {
|
onIsHoveredChanged: {
|
||||||
@@ -148,8 +147,9 @@ Item {
|
|||||||
interval: 500
|
interval: 500
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (appData && appData.isPinned)
|
if (appData && appData.isPinned) {
|
||||||
longPressing = true
|
longPressing = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +162,7 @@ Item {
|
|||||||
cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
|
cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
onPressed: mouse => {
|
onPressed: mouse => {
|
||||||
if (mouse.button === Qt.LeftButton && appData
|
if (mouse.button === Qt.LeftButton && appData && appData.isPinned) {
|
||||||
&& appData.isPinned) {
|
|
||||||
dragStartPos = Qt.point(mouse.x, mouse.y)
|
dragStartPos = Qt.point(mouse.x, mouse.y)
|
||||||
longPressTimer.start()
|
longPressTimer.start()
|
||||||
}
|
}
|
||||||
@@ -171,9 +170,9 @@ Item {
|
|||||||
onReleased: mouse => {
|
onReleased: mouse => {
|
||||||
longPressTimer.stop()
|
longPressTimer.stop()
|
||||||
if (longPressing) {
|
if (longPressing) {
|
||||||
if (dragging && targetIndex >= 0
|
if (dragging && targetIndex >= 0 && targetIndex !== originalIndex && dockApps) {
|
||||||
&& targetIndex !== originalIndex && dockApps)
|
dockApps.movePinnedApp(originalIndex, targetIndex)
|
||||||
dockApps.movePinnedApp(originalIndex, targetIndex)
|
}
|
||||||
|
|
||||||
longPressing = false
|
longPressing = false
|
||||||
dragging = false
|
dragging = false
|
||||||
@@ -184,10 +183,7 @@ Item {
|
|||||||
}
|
}
|
||||||
onPositionChanged: mouse => {
|
onPositionChanged: mouse => {
|
||||||
if (longPressing && !dragging) {
|
if (longPressing && !dragging) {
|
||||||
var distance = Math.sqrt(
|
const distance = Math.sqrt(Math.pow(mouse.x - dragStartPos.x, 2) + Math.pow(mouse.y - dragStartPos.y, 2))
|
||||||
Math.pow(mouse.x - dragStartPos.x,
|
|
||||||
2) + Math.pow(
|
|
||||||
mouse.y - dragStartPos.y, 2))
|
|
||||||
if (distance > 5) {
|
if (distance > 5) {
|
||||||
dragging = true
|
dragging = true
|
||||||
targetIndex = index
|
targetIndex = index
|
||||||
@@ -195,79 +191,66 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
dragOffset = Qt.point(
|
dragOffset = Qt.point(mouse.x - dragStartPos.x, mouse.y - dragStartPos.y)
|
||||||
mouse.x - dragStartPos.x,
|
|
||||||
mouse.y - dragStartPos.y)
|
|
||||||
if (dockApps) {
|
if (dockApps) {
|
||||||
var threshold = 40
|
const threshold = 40
|
||||||
var newTargetIndex = targetIndex
|
let newTargetIndex = targetIndex
|
||||||
if (dragOffset.x > threshold
|
if (dragOffset.x > threshold && targetIndex < dockApps.pinnedAppCount - 1) {
|
||||||
&& targetIndex < dockApps.pinnedAppCount - 1)
|
newTargetIndex = targetIndex + 1
|
||||||
newTargetIndex = targetIndex + 1
|
} else if (dragOffset.x < -threshold && targetIndex > 0) {
|
||||||
else if (dragOffset.x < -threshold
|
newTargetIndex = targetIndex - 1
|
||||||
&& targetIndex > 0)
|
}
|
||||||
newTargetIndex = targetIndex - 1
|
|
||||||
if (newTargetIndex !== targetIndex) {
|
if (newTargetIndex !== targetIndex) {
|
||||||
targetIndex = newTargetIndex
|
targetIndex = newTargetIndex
|
||||||
dragStartPos = Qt.point(mouse.x,
|
dragStartPos = Qt.point(mouse.x, mouse.y)
|
||||||
mouse.y)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (!appData || longPressing)
|
if (!appData || longPressing) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
// Handle based on type
|
|
||||||
if (appData.type === "pinned") {
|
if (appData.type === "pinned") {
|
||||||
// Launch the pinned app
|
|
||||||
if (appData && appData.appId) {
|
if (appData && appData.appId) {
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(
|
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
||||||
appData.appId)
|
if (desktopEntry) {
|
||||||
if (desktopEntry)
|
AppUsageHistoryData.addAppUsage({
|
||||||
AppUsageHistoryData.addAppUsage({
|
"id": appData.appId,
|
||||||
"id": appData.appId,
|
"name": desktopEntry.name || appData.appId,
|
||||||
"name": desktopEntry.name
|
"icon": desktopEntry.icon || "",
|
||||||
|| appData.appId,
|
"exec": desktopEntry.exec || "",
|
||||||
"icon": desktopEntry.icon
|
"comment": desktopEntry.comment || ""
|
||||||
|| "",
|
})
|
||||||
"exec": desktopEntry.exec
|
}
|
||||||
|| "",
|
|
||||||
"comment": desktopEntry.comment || ""
|
|
||||||
})
|
|
||||||
|
|
||||||
desktopEntry.execute()
|
desktopEntry.execute()
|
||||||
}
|
}
|
||||||
} else if (appData.type === "window") {
|
} else if (appData.type === "window") {
|
||||||
var toplevel = getToplevelObject()
|
const toplevel = getToplevelObject()
|
||||||
if (toplevel) {
|
if (toplevel) {
|
||||||
toplevel.activate()
|
toplevel.activate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.MiddleButton) {
|
} else if (mouse.button === Qt.MiddleButton) {
|
||||||
if (appData && appData.appId) {
|
if (appData && appData.appId) {
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(
|
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
||||||
appData.appId)
|
if (desktopEntry) {
|
||||||
if (desktopEntry)
|
AppUsageHistoryData.addAppUsage({
|
||||||
AppUsageHistoryData.addAppUsage({
|
"id": appData.appId,
|
||||||
"id": appData.appId,
|
"name": desktopEntry.name || appData.appId,
|
||||||
"name": desktopEntry.name
|
"icon": desktopEntry.icon || "",
|
||||||
|| appData.appId,
|
"exec": desktopEntry.exec || "",
|
||||||
"icon": desktopEntry.icon
|
"comment": desktopEntry.comment || ""
|
||||||
|| "",
|
})
|
||||||
"exec": desktopEntry.exec
|
}
|
||||||
|| "",
|
desktopEntry.execute()
|
||||||
"comment": desktopEntry.comment
|
|
||||||
|| ""
|
|
||||||
})
|
|
||||||
|
|
||||||
desktopEntry.execute()
|
|
||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
if (contextMenu)
|
if (contextMenu) {
|
||||||
contextMenu.showForButton(root, appData, 40)
|
contextMenu.showForButton(root, appData, 40)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,8 +261,10 @@ Item {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
implicitSize: 40
|
implicitSize: 40
|
||||||
source: {
|
source: {
|
||||||
if (appData.appId === "__SEPARATOR__") return ""
|
if (appData.appId === "__SEPARATOR__") {
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(Paths.moddedAppId(appData.appId))
|
return ""
|
||||||
|
}
|
||||||
|
const desktopEntry = DesktopEntries.heuristicLookup(Paths.moddedAppId(appData.appId))
|
||||||
return desktopEntry && desktopEntry.icon ? Quickshell.iconPath(desktopEntry.icon, true) : ""
|
return desktopEntry && desktopEntry.icon ? Quickshell.iconPath(desktopEntry.icon, true) : ""
|
||||||
}
|
}
|
||||||
mipmap: true
|
mipmap: true
|
||||||
@@ -301,12 +286,14 @@ Item {
|
|||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: {
|
text: {
|
||||||
if (!appData || !appData.appId)
|
if (!appData || !appData.appId) {
|
||||||
return "?"
|
return "?"
|
||||||
|
}
|
||||||
|
|
||||||
var desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
|
||||||
if (desktopEntry && desktopEntry.name)
|
if (desktopEntry && desktopEntry.name) {
|
||||||
return desktopEntry.name.charAt(0).toUpperCase()
|
return desktopEntry.name.charAt(0).toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
return appData.appId.charAt(0).toUpperCase()
|
return appData.appId.charAt(0).toUpperCase()
|
||||||
}
|
}
|
||||||
@@ -326,17 +313,17 @@ Item {
|
|||||||
radius: 1
|
radius: 1
|
||||||
visible: appData && (appData.isRunning || appData.type === "window")
|
visible: appData && (appData.isRunning || appData.type === "window")
|
||||||
color: {
|
color: {
|
||||||
if (!appData)
|
if (!appData) {
|
||||||
return "transparent"
|
return "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
// For window type, check if focused using reactive property
|
if (isWindowFocused) {
|
||||||
if (isWindowFocused)
|
|
||||||
return Theme.primary
|
return Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
// For running apps, show dimmer indicator
|
if (appData.isRunning || appData.type === "window") {
|
||||||
if (appData.isRunning || appData.type === "window")
|
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
||||||
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
}
|
||||||
Theme.surfaceText.b, 0.6)
|
|
||||||
|
|
||||||
return "transparent"
|
return "transparent"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,16 @@ Item {
|
|||||||
implicitHeight: row.height
|
implicitHeight: row.height
|
||||||
|
|
||||||
function movePinnedApp(fromIndex, toIndex) {
|
function movePinnedApp(fromIndex, toIndex) {
|
||||||
if (fromIndex === toIndex)
|
if (fromIndex === toIndex) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var currentPinned = [...(SessionData.pinnedApps || [])]
|
const currentPinned = [...(SessionData.pinnedApps || [])]
|
||||||
if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0
|
if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0 || toIndex >= currentPinned.length) {
|
||||||
|| toIndex >= currentPinned.length)
|
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var movedApp = currentPinned.splice(fromIndex, 1)[0]
|
const movedApp = currentPinned.splice(fromIndex, 1)[0]
|
||||||
currentPinned.splice(toIndex, 0, movedApp)
|
currentPinned.splice(toIndex, 0, movedApp)
|
||||||
|
|
||||||
SessionData.setPinnedApps(currentPinned)
|
SessionData.setPinnedApps(currentPinned)
|
||||||
@@ -47,60 +48,48 @@ Item {
|
|||||||
function updateModel() {
|
function updateModel() {
|
||||||
clear()
|
clear()
|
||||||
|
|
||||||
var items = []
|
const items = []
|
||||||
var pinnedApps = [...(SessionData.pinnedApps || [])]
|
const pinnedApps = [...(SessionData.pinnedApps || [])]
|
||||||
|
|
||||||
// First section: Pinned apps (always visible, not representing running windows)
|
|
||||||
pinnedApps.forEach(appId => {
|
pinnedApps.forEach(appId => {
|
||||||
items.push({
|
items.push({
|
||||||
"type": "pinned",
|
"type": "pinned",
|
||||||
"appId": appId,
|
"appId": appId,
|
||||||
"windowId": -1,
|
"windowId": -1,
|
||||||
"windowTitle"// Use -1 instead of null to avoid ListModel warnings
|
"windowTitle": "",
|
||||||
: "",
|
|
||||||
"workspaceId": -1,
|
"workspaceId": -1,
|
||||||
"isPinned"// Use -1 instead of null
|
"isPinned": true,
|
||||||
: true,
|
"isRunning": false
|
||||||
"isRunning": false,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
root.pinnedAppCount = pinnedApps.length
|
root.pinnedAppCount = pinnedApps.length
|
||||||
|
|
||||||
// Get sorted toplevels from CompositorService
|
const sortedToplevels = CompositorService.sortedToplevels
|
||||||
var sortedToplevels = CompositorService.sortedToplevels
|
|
||||||
|
if (pinnedApps.length > 0 && sortedToplevels.length > 0) {
|
||||||
// Add separator between pinned and running if both exist
|
|
||||||
if (pinnedApps.length > 0
|
|
||||||
&& sortedToplevels.length > 0) {
|
|
||||||
items.push({
|
items.push({
|
||||||
"type": "separator",
|
"type": "separator",
|
||||||
"appId": "__SEPARATOR__",
|
"appId": "__SEPARATOR__",
|
||||||
"windowId": -1,
|
"windowId": -1,
|
||||||
"windowTitle"// Use -1 instead of null
|
"windowTitle": "",
|
||||||
: "",
|
|
||||||
"workspaceId": -1,
|
"workspaceId": -1,
|
||||||
"isPinned"// Use -1 instead of null
|
"isPinned": false,
|
||||||
: false,
|
|
||||||
"isRunning": false,
|
"isRunning": false,
|
||||||
"isFocused": false
|
"isFocused": false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second section: Running windows (sorted using Theme.sortToplevels)
|
|
||||||
sortedToplevels.forEach((toplevel, index) => {
|
sortedToplevels.forEach((toplevel, index) => {
|
||||||
// Limit window title length for tooltip
|
const title = toplevel.title || "(Unnamed)"
|
||||||
var title = toplevel.title || "(Unnamed)"
|
const truncatedTitle = title.length > 50 ? title.substring(0, 47) + "..." : title
|
||||||
if (title.length > 50) {
|
const uniqueId = toplevel.title + "|" + (toplevel.appId || "") + "|" + index
|
||||||
title = title.substring(0, 47) + "..."
|
|
||||||
}
|
|
||||||
var uniqueId = toplevel.title + "|" + (toplevel.appId || "") + "|" + index
|
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
"type": "window",
|
"type": "window",
|
||||||
"appId": toplevel.appId,
|
"appId": toplevel.appId,
|
||||||
"windowId": index,
|
"windowId": index,
|
||||||
"windowTitle": title,
|
"windowTitle": truncatedTitle,
|
||||||
"workspaceId": -1,
|
"workspaceId": -1,
|
||||||
"isPinned": false,
|
"isPinned": false,
|
||||||
"isRunning": true,
|
"isRunning": true,
|
||||||
@@ -108,9 +97,7 @@ Item {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => append(item))
|
||||||
append(item)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +112,7 @@ Item {
|
|||||||
visible: model.type === "separator"
|
visible: model.type === "separator"
|
||||||
width: 2
|
width: 2
|
||||||
height: 20
|
height: 20
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||||
Theme.outline.b, 0.3)
|
|
||||||
radius: 1
|
radius: 1
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
@@ -159,8 +145,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SessionData
|
target: SessionData
|
||||||
function onPinnedAppsChanged() {
|
function onPinnedAppsChanged() {
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ PanelWindow {
|
|||||||
appData = data
|
appData = data
|
||||||
dockVisibleHeight = dockHeight || 40
|
dockVisibleHeight = dockHeight || 40
|
||||||
|
|
||||||
var dockWindow = button.Window.window
|
const dockWindow = button.Window.window
|
||||||
if (dockWindow) {
|
if (dockWindow) {
|
||||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||||
var s = Quickshell.screens[i]
|
const s = Quickshell.screens[i]
|
||||||
if (dockWindow.x >= s.x && dockWindow.x < s.x + s.width) {
|
if (dockWindow.x >= s.x && dockWindow.x < s.x + s.width) {
|
||||||
root.screen = s
|
root.screen = s
|
||||||
break
|
break
|
||||||
@@ -55,8 +55,11 @@ PanelWindow {
|
|||||||
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
|
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
|
||||||
|
|
||||||
onAnchorItemChanged: updatePosition()
|
onAnchorItemChanged: updatePosition()
|
||||||
onVisibleChanged: if (visible)
|
onVisibleChanged: {
|
||||||
updatePosition()
|
if (visible) {
|
||||||
|
updatePosition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updatePosition() {
|
function updatePosition() {
|
||||||
if (!anchorItem) {
|
if (!anchorItem) {
|
||||||
@@ -64,40 +67,40 @@ PanelWindow {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var dockWindow = anchorItem.Window.window
|
const dockWindow = anchorItem.Window.window
|
||||||
if (!dockWindow) {
|
if (!dockWindow) {
|
||||||
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
|
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonPosInDock = anchorItem.mapToItem(dockWindow.contentItem, 0, 0)
|
const buttonPosInDock = anchorItem.mapToItem(dockWindow.contentItem, 0, 0)
|
||||||
|
let actualDockHeight = root.dockVisibleHeight
|
||||||
var actualDockHeight = root.dockVisibleHeight // fallback
|
|
||||||
|
|
||||||
function findDockBackground(item) {
|
function findDockBackground(item) {
|
||||||
if (item.objectName === "dockBackground") {
|
if (item.objectName === "dockBackground") {
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
for (var i = 0; i < item.children.length; i++) {
|
for (var i = 0; i < item.children.length; i++) {
|
||||||
var found = findDockBackground(item.children[i])
|
const found = findDockBackground(item.children[i])
|
||||||
if (found)
|
if (found) {
|
||||||
return found
|
return found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
var dockBackground = findDockBackground(dockWindow.contentItem)
|
const dockBackground = findDockBackground(dockWindow.contentItem)
|
||||||
if (dockBackground) {
|
if (dockBackground) {
|
||||||
actualDockHeight = dockBackground.height
|
actualDockHeight = dockBackground.height
|
||||||
}
|
}
|
||||||
|
|
||||||
var dockBottomMargin = 16 // The dock has bottom margin
|
const dockBottomMargin = 16
|
||||||
var buttonScreenY = root.screen.height - actualDockHeight - dockBottomMargin - 20
|
const buttonScreenY = root.screen.height - actualDockHeight - dockBottomMargin - 20
|
||||||
|
|
||||||
var dockContentWidth = dockWindow.width
|
const dockContentWidth = dockWindow.width
|
||||||
var screenWidth = root.screen.width
|
const screenWidth = root.screen.width
|
||||||
var dockLeftMargin = Math.round((screenWidth - dockContentWidth) / 2)
|
const dockLeftMargin = Math.round((screenWidth - dockContentWidth) / 2)
|
||||||
var buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2
|
const buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2
|
||||||
|
|
||||||
anchorPos = Qt.point(buttonScreenX, buttonScreenY)
|
anchorPos = Qt.point(buttonScreenX, buttonScreenY)
|
||||||
}
|
}
|
||||||
@@ -105,22 +108,19 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: menuContainer
|
id: menuContainer
|
||||||
|
|
||||||
width: Math.min(400,
|
width: Math.min(400, Math.max(200, menuColumn.implicitWidth + Theme.spacingS * 2))
|
||||||
Math.max(200,
|
|
||||||
menuColumn.implicitWidth + Theme.spacingS * 2))
|
|
||||||
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
|
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
|
||||||
|
|
||||||
x: {
|
x: {
|
||||||
var left = 10
|
const left = 10
|
||||||
var right = root.width - width - 10
|
const right = root.width - width - 10
|
||||||
var want = root.anchorPos.x - width / 2
|
const want = root.anchorPos.x - width / 2
|
||||||
return Math.max(left, Math.min(right, want))
|
return Math.max(left, Math.min(right, want))
|
||||||
}
|
}
|
||||||
y: Math.max(10, root.anchorPos.y - height + 30)
|
y: Math.max(10, root.anchorPos.y - height + 30)
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
border.width: 1
|
||||||
opacity: showContextMenu ? 1 : 0
|
opacity: showContextMenu ? 1 : 0
|
||||||
scale: showContextMenu ? 1 : 0.85
|
scale: showContextMenu ? 1 : 0.85
|
||||||
@@ -148,10 +148,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 28
|
height: 28
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r,
|
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -159,8 +156,7 @@ PanelWindow {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.spacingS
|
anchors.rightMargin: Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: root.appData
|
text: root.appData && root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
|
||||||
&& root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -174,8 +170,9 @@ PanelWindow {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!root.appData)
|
if (!root.appData) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
if (root.appData.isPinned) {
|
if (root.appData.isPinned) {
|
||||||
SessionData.removePinnedApp(root.appData.appId)
|
SessionData.removePinnedApp(root.appData.appId)
|
||||||
} else {
|
} else {
|
||||||
@@ -190,16 +187,14 @@ PanelWindow {
|
|||||||
visible: root.appData && root.appData.type === "window"
|
visible: root.appData && root.appData.type === "window"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
Theme.outline.b, 0.2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.appData && root.appData.type === "window"
|
visible: root.appData && root.appData.type === "window"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
Theme.outline.b, 0.2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -207,11 +202,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 28
|
height: 28
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: closeArea.containsMouse ? Qt.rgba(
|
color: closeArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
|
||||||
Theme.error.r,
|
|
||||||
Theme.error.g,
|
|
||||||
Theme.error.b,
|
|
||||||
0.12) : "transparent"
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
onExited: (exitCode, exitStatus) => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
console.warn("Failed to get session path, exit code:", exitCode)
|
console.warn("Failed to get session path, exit code:", exitCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
@@ -52,8 +52,7 @@ Item {
|
|||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
if (text.includes("true")) {
|
if (text.includes("true")) {
|
||||||
console.log(
|
console.log("Session is locked on startup, activating lock screen")
|
||||||
"Session is locked on startup, activating lock screen")
|
|
||||||
LockScreenService.resetState()
|
LockScreenService.resetState()
|
||||||
loader.activeAsync = true
|
loader.activeAsync = true
|
||||||
}
|
}
|
||||||
@@ -61,11 +60,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
onExited: (exitCode, exitStatus) => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
console.warn("Failed to check initial lock state, exit code:",
|
console.warn("Failed to check initial lock state, exit code:", exitCode)
|
||||||
exitCode)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
@@ -77,32 +75,29 @@ Item {
|
|||||||
splitMarker: "\n"
|
splitMarker: "\n"
|
||||||
|
|
||||||
onRead: line => {
|
onRead: line => {
|
||||||
if (line.includes("org.freedesktop.login1.Session.Lock")) {
|
if (line.includes("org.freedesktop.login1.Session.Lock")) {
|
||||||
console.log("login1: Lock signal received -> show lock")
|
console.log("login1: Lock signal received -> show lock")
|
||||||
LockScreenService.resetState()
|
LockScreenService.resetState()
|
||||||
loader.activeAsync = true
|
loader.activeAsync = true
|
||||||
} else if (line.includes(
|
} else if (line.includes("org.freedesktop.login1.Session.Unlock")) {
|
||||||
"org.freedesktop.login1.Session.Unlock")) {
|
console.log("login1: Unlock signal received -> hide lock")
|
||||||
console.log("login1: Unlock signal received -> hide lock")
|
loader.active = false
|
||||||
loader.active = false
|
} else if (line.includes("LockedHint") && line.includes("true")) {
|
||||||
} else if (line.includes("LockedHint") && line.includes(
|
console.log("login1: LockedHint=true -> show lock")
|
||||||
"true")) {
|
LockScreenService.resetState()
|
||||||
console.log("login1: LockedHint=true -> show lock")
|
loader.activeAsync = true
|
||||||
LockScreenService.resetState()
|
} else if (line.includes("LockedHint") && line.includes("false")) {
|
||||||
loader.activeAsync = true
|
console.log("login1: LockedHint=false -> hide lock")
|
||||||
} else if (line.includes("LockedHint") && line.includes(
|
loader.active = false
|
||||||
"false")) {
|
}
|
||||||
console.log("login1: LockedHint=false -> hide lock")
|
}
|
||||||
loader.active = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
onExited: (exitCode, exitStatus) => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
console.warn("gdbus monitor failed, exit code:", exitCode)
|
console.warn("gdbus monitor failed, exit code:", exitCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -117,8 +112,9 @@ Item {
|
|||||||
locked: true
|
locked: true
|
||||||
|
|
||||||
onLockedChanged: {
|
onLockedChanged: {
|
||||||
if (!locked)
|
if (!locked) {
|
||||||
loader.active = false
|
loader.active = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LockSurface {
|
LockSurface {
|
||||||
@@ -126,8 +122,8 @@ Item {
|
|||||||
lock: sessionLock
|
lock: sessionLock
|
||||||
sharedPasswordBuffer: sessionLock.sharedPasswordBuffer
|
sharedPasswordBuffer: sessionLock.sharedPasswordBuffer
|
||||||
onPasswordChanged: newPassword => {
|
onPasswordChanged: newPassword => {
|
||||||
sessionLock.sharedPasswordBuffer = newPassword
|
sessionLock.sharedPasswordBuffer = newPassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import Quickshell
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Services.Pam
|
import Quickshell.Services.Pam
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modals
|
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -15,27 +14,47 @@ Item {
|
|||||||
|
|
||||||
property string passwordBuffer: ""
|
property string passwordBuffer: ""
|
||||||
property bool demoMode: false
|
property bool demoMode: false
|
||||||
property var powerModal: null
|
|
||||||
property string confirmAction: ""
|
|
||||||
|
|
||||||
signal unlockRequested
|
signal unlockRequested
|
||||||
|
|
||||||
|
// Internal power dialog state
|
||||||
|
property bool powerDialogVisible: false
|
||||||
|
property string powerDialogTitle: ""
|
||||||
|
property string powerDialogMessage: ""
|
||||||
|
property string powerDialogConfirmText: ""
|
||||||
|
property color powerDialogConfirmColor: Theme.primary
|
||||||
|
property var powerDialogOnConfirm: function() {}
|
||||||
|
|
||||||
|
function showPowerDialog(title, message, confirmText, confirmColor, onConfirm) {
|
||||||
|
powerDialogTitle = title
|
||||||
|
powerDialogMessage = message
|
||||||
|
powerDialogConfirmText = confirmText
|
||||||
|
powerDialogConfirmColor = confirmColor
|
||||||
|
powerDialogOnConfirm = onConfirm
|
||||||
|
powerDialogVisible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function hidePowerDialog() {
|
||||||
|
powerDialogVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
LockScreenService.pickRandomFact()
|
LockScreenService.pickRandomFact()
|
||||||
|
}
|
||||||
|
|
||||||
WeatherService.addRef()
|
WeatherService.addRef()
|
||||||
UserInfoService.refreshUserInfo()
|
UserInfoService.refreshUserInfo()
|
||||||
}
|
}
|
||||||
onDemoModeChanged: {
|
onDemoModeChanged: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
LockScreenService.pickRandomFact()
|
LockScreenService.pickRandomFact()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
WeatherService.removeRef()
|
WeatherService.removeRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backdrop for when no wallpaper is set
|
|
||||||
Loader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: !SessionData.wallpaperPath
|
active: !SessionData.wallpaperPath
|
||||||
@@ -159,11 +178,13 @@ Item {
|
|||||||
id: profileImageLoader
|
id: profileImageLoader
|
||||||
|
|
||||||
source: {
|
source: {
|
||||||
if (PortalService.profileImage === "")
|
if (PortalService.profileImage === "") {
|
||||||
return ""
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
if (PortalService.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/")) {
|
||||||
return "file://" + PortalService.profileImage
|
return "file://" + PortalService.profileImage
|
||||||
|
}
|
||||||
|
|
||||||
return PortalService.profileImage
|
return PortalService.profileImage
|
||||||
}
|
}
|
||||||
@@ -221,8 +242,7 @@ Item {
|
|||||||
name: "warning"
|
name: "warning"
|
||||||
size: Theme.iconSize + 4
|
size: Theme.iconSize + 4
|
||||||
color: Theme.primaryText
|
color: Theme.primaryText
|
||||||
visible: PortalService.profileImage !== ""
|
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
|
||||||
&& profileImageLoader.status === Image.Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,11 +252,8 @@ Item {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 60
|
Layout.preferredHeight: 60
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
|
||||||
Theme.surfaceContainer.g,
|
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(1, 1, 1, 0.3)
|
||||||
Theme.surfaceContainer.b, 0.9)
|
|
||||||
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(
|
|
||||||
1, 1, 1, 0.3)
|
|
||||||
border.width: passwordField.activeFocus ? 2 : 1
|
border.width: passwordField.activeFocus ? 2 : 1
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
@@ -255,29 +272,44 @@ Item {
|
|||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
|
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
|
||||||
anchors.rightMargin: (revealButton.visible ? revealButton.width : 0) + (virtualKeyboardButton.visible ? virtualKeyboardButton.width : 0) + (enterButton.visible ? enterButton.width + 2 : 0) + (loadingSpinner.visible ? loadingSpinner.width + Theme.spacingM : Theme.spacingM)
|
anchors.rightMargin: {
|
||||||
|
let margin = Theme.spacingM
|
||||||
|
if (loadingSpinner.visible) {
|
||||||
|
margin += loadingSpinner.width
|
||||||
|
}
|
||||||
|
if (enterButton.visible) {
|
||||||
|
margin += enterButton.width + 2
|
||||||
|
}
|
||||||
|
if (virtualKeyboardButton.visible) {
|
||||||
|
margin += virtualKeyboardButton.width
|
||||||
|
}
|
||||||
|
if (revealButton.visible) {
|
||||||
|
margin += revealButton.width
|
||||||
|
}
|
||||||
|
return margin
|
||||||
|
}
|
||||||
opacity: 0
|
opacity: 0
|
||||||
focus: !demoMode
|
focus: !demoMode
|
||||||
enabled: !demoMode
|
enabled: !demoMode
|
||||||
echoMode: parent.showPassword ? TextInput.Normal : TextInput.Password
|
echoMode: parent.showPassword ? TextInput.Normal : TextInput.Password
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (!demoMode)
|
if (!demoMode) {
|
||||||
root.passwordBuffer = text
|
root.passwordBuffer = text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
if (!demoMode && root.passwordBuffer.length > 0
|
if (!demoMode && root.passwordBuffer.length > 0 && !pam.active) {
|
||||||
&& !pam.active) {
|
|
||||||
console.log("Enter pressed, starting PAM authentication")
|
console.log("Enter pressed, starting PAM authentication")
|
||||||
pam.start()
|
pam.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keys.onPressed: event => {
|
Keys.onPressed: event => {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (pam.active) {
|
if (pam.active) {
|
||||||
console.log(
|
console.log("PAM is active, ignoring input")
|
||||||
"PAM is active, ignoring input")
|
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -292,38 +324,35 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardController {
|
KeyboardController {
|
||||||
id: keyboardController
|
id: keyboardController
|
||||||
target: passwordField
|
target: passwordField
|
||||||
rootObject: root
|
rootObject: root
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: placeholder
|
id: placeholder
|
||||||
|
|
||||||
property string pamState: ""
|
|
||||||
|
|
||||||
anchors.left: lockIcon.right
|
anchors.left: lockIcon.right
|
||||||
anchors.leftMargin: Theme.spacingM
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: (revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right))))
|
anchors.right: (revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right))))
|
||||||
anchors.rightMargin: 2
|
anchors.rightMargin: 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: {
|
text: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
return ""
|
return ""
|
||||||
|
}
|
||||||
if (LockScreenService.unlocking)
|
if (LockScreenService.unlocking) {
|
||||||
return "Unlocking..."
|
return "Unlocking..."
|
||||||
|
}
|
||||||
if (pam.active)
|
if (pam.active) {
|
||||||
return "Authenticating..."
|
return "Authenticating..."
|
||||||
|
}
|
||||||
return "Password..."
|
return "Password..."
|
||||||
}
|
}
|
||||||
color: LockScreenService.unlocking ? Theme.primary : (pam.active ? Theme.primary : Theme.outline)
|
color: LockScreenService.unlocking ? Theme.primary : (pam.active ? Theme.primary : Theme.outline)
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
opacity: (demoMode
|
opacity: (demoMode || root.passwordBuffer.length === 0) ? 1 : 0
|
||||||
|| root.passwordBuffer.length === 0) ? 1 : 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -347,19 +376,17 @@ Item {
|
|||||||
anchors.rightMargin: 2
|
anchors.rightMargin: 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: {
|
text: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
return "••••••••"
|
return "••••••••"
|
||||||
else if (parent.showPassword)
|
}
|
||||||
|
if (parent.showPassword) {
|
||||||
return root.passwordBuffer
|
return root.passwordBuffer
|
||||||
else
|
}
|
||||||
return "•".repeat(
|
return "•".repeat(Math.min(root.passwordBuffer.length, 25))
|
||||||
Math.min(
|
|
||||||
root.passwordBuffer.length, 25))
|
|
||||||
}
|
}
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.pixelSize: parent.showPassword ? Theme.fontSizeMedium : Theme.fontSizeLarge
|
font.pixelSize: parent.showPassword ? Theme.fontSizeMedium : Theme.fontSizeLarge
|
||||||
opacity: (demoMode
|
opacity: (demoMode || root.passwordBuffer.length > 0) ? 1 : 0
|
||||||
|| root.passwordBuffer.length > 0) ? 1 : 0
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
@@ -378,12 +405,11 @@ Item {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
iconName: parent.showPassword ? "visibility_off" : "visibility"
|
iconName: parent.showPassword ? "visibility_off" : "visibility"
|
||||||
buttonSize: 32
|
buttonSize: 32
|
||||||
visible: !demoMode && root.passwordBuffer.length > 0
|
visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active && !LockScreenService.unlocking
|
||||||
&& !pam.active && !LockScreenService.unlocking
|
|
||||||
enabled: visible
|
enabled: visible
|
||||||
onClicked: parent.showPassword = !parent.showPassword
|
onClicked: parent.showPassword = !parent.showPassword
|
||||||
}
|
}
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
id: virtualKeyboardButton
|
id: virtualKeyboardButton
|
||||||
|
|
||||||
anchors.right: enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right)
|
anchors.right: enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right)
|
||||||
@@ -393,15 +419,12 @@ Item {
|
|||||||
buttonSize: 32
|
buttonSize: 32
|
||||||
visible: !demoMode && !pam.active && !LockScreenService.unlocking
|
visible: !demoMode && !pam.active && !LockScreenService.unlocking
|
||||||
enabled: visible
|
enabled: visible
|
||||||
onClicked:
|
onClicked: {
|
||||||
{
|
if (keyboardController.isKeyboardActive) {
|
||||||
if(keyboardController.isKeyboardActive)
|
|
||||||
{
|
|
||||||
keyboardController.hide()
|
keyboardController.hide()
|
||||||
} else
|
} else {
|
||||||
{
|
keyboardController.show()
|
||||||
keyboardController.show()
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,8 +438,7 @@ Item {
|
|||||||
height: 24
|
height: 24
|
||||||
radius: 12
|
radius: 12
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
visible: !demoMode && (pam.active
|
visible: !demoMode && (pam.active || LockScreenService.unlocking)
|
||||||
|| LockScreenService.unlocking)
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -456,9 +478,7 @@ Item {
|
|||||||
radius: 10
|
radius: 10
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
border.color: Qt.rgba(Theme.primary.r,
|
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b, 0.3)
|
|
||||||
border.width: 2
|
border.width: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,15 +496,11 @@ Item {
|
|||||||
height: parent.height / 2
|
height: parent.height / 2
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r,
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
|
||||||
Theme.surfaceContainer.g,
|
|
||||||
Theme.surfaceContainer.b,
|
|
||||||
0.9)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RotationAnimation on rotation {
|
RotationAnimation on rotation {
|
||||||
running: pam.active
|
running: pam.active && !LockScreenService.unlocking
|
||||||
&& !LockScreenService.unlocking
|
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
duration: Anims.durLong
|
duration: Anims.durLong
|
||||||
from: 0
|
from: 0
|
||||||
@@ -502,9 +518,7 @@ Item {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
iconName: "keyboard_return"
|
iconName: "keyboard_return"
|
||||||
buttonSize: 36
|
buttonSize: 36
|
||||||
visible: (demoMode || (root.passwordBuffer.length > 0
|
visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active && !LockScreenService.unlocking))
|
||||||
&& !pam.active
|
|
||||||
&& !LockScreenService.unlocking))
|
|
||||||
enabled: !demoMode
|
enabled: !demoMode
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!demoMode) {
|
if (!demoMode) {
|
||||||
@@ -534,15 +548,15 @@ Item {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: LockScreenService.pamState ? 20 : 0
|
Layout.preferredHeight: LockScreenService.pamState ? 20 : 0
|
||||||
text: {
|
text: {
|
||||||
if (LockScreenService.pamState === "error")
|
if (LockScreenService.pamState === "error") {
|
||||||
return "Authentication error - try again"
|
return "Authentication error - try again"
|
||||||
|
}
|
||||||
if (LockScreenService.pamState === "max")
|
if (LockScreenService.pamState === "max") {
|
||||||
return "Too many attempts - locked out"
|
return "Too many attempts - locked out"
|
||||||
|
}
|
||||||
if (LockScreenService.pamState === "fail")
|
if (LockScreenService.pamState === "fail") {
|
||||||
return "Incorrect password - try again"
|
return "Incorrect password - try again"
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
@@ -578,22 +592,19 @@ Item {
|
|||||||
visible: demoMode
|
visible: demoMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status bar at top
|
|
||||||
Row {
|
Row {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.margins: Theme.spacingXL
|
anchors.margins: Theme.spacingXL
|
||||||
spacing: Theme.spacingL
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
// Weather section
|
|
||||||
Row {
|
Row {
|
||||||
spacing: 6
|
spacing: 6
|
||||||
visible: WeatherService.weather.available
|
visible: WeatherService.weather.available
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: WeatherService.getWeatherIcon(
|
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||||
WeatherService.weather.wCode)
|
|
||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: "white"
|
color: "white"
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -608,91 +619,63 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separator
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 1
|
width: 1
|
||||||
height: 24
|
height: 24
|
||||||
color: Qt.rgba(255, 255, 255, 0.2)
|
color: Qt.rgba(255, 255, 255, 0.2)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: WeatherService.weather.available
|
visible: WeatherService.weather.available && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio) || BatteryService.batteryAvailable)
|
||||||
&& (NetworkService.networkStatus !== "disconnected"
|
|
||||||
|| BluetoothService.enabled
|
|
||||||
|| (AudioService.sink && AudioService.sink.audio)
|
|
||||||
|| BatteryService.batteryAvailable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// System status icons
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: NetworkService.networkStatus !== "disconnected"
|
visible: NetworkService.networkStatus !== "disconnected" || (BluetoothService.available && BluetoothService.enabled) || (AudioService.sink && AudioService.sink.audio)
|
||||||
|| (BluetoothService.available
|
|
||||||
&& BluetoothService.enabled)
|
|
||||||
|| (AudioService.sink && AudioService.sink.audio)
|
|
||||||
|
|
||||||
// Network icon
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: {
|
name: NetworkService.networkStatus === "ethernet" ? "lan" : NetworkService.wifiSignalIcon
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "lan"
|
|
||||||
}
|
|
||||||
return NetworkService.wifiSignalIcon
|
|
||||||
}
|
|
||||||
size: Theme.iconSize - 2
|
size: Theme.iconSize - 2
|
||||||
color: NetworkService.networkStatus
|
color: NetworkService.networkStatus !== "disconnected" ? "white" : Qt.rgba(255, 255, 255, 0.5)
|
||||||
!== "disconnected" ? "white" : Qt.rgba(255,
|
|
||||||
255, 255, 0.5)
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: NetworkService.networkStatus !== "disconnected"
|
visible: NetworkService.networkStatus !== "disconnected"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bluetooth icon
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "bluetooth"
|
name: "bluetooth"
|
||||||
size: Theme.iconSize - 2
|
size: Theme.iconSize - 2
|
||||||
color: "white"
|
color: "white"
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: BluetoothService.available
|
visible: BluetoothService.available && BluetoothService.enabled
|
||||||
&& BluetoothService.enabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volume icon
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: {
|
name: {
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
if (!AudioService.sink?.audio) {
|
||||||
if (AudioService.sink.audio.muted
|
return "volume_up"
|
||||||
|| AudioService.sink.audio.volume === 0)
|
}
|
||||||
return "volume_off"
|
if (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0) {
|
||||||
else if (AudioService.sink.audio.volume * 100 < 33)
|
return "volume_off"
|
||||||
return "volume_down"
|
}
|
||||||
else
|
if (AudioService.sink.audio.volume * 100 < 33) {
|
||||||
return "volume_up"
|
return "volume_down"
|
||||||
}
|
}
|
||||||
return "volume_up"
|
return "volume_up"
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 2
|
size: Theme.iconSize - 2
|
||||||
color: (AudioService.sink && AudioService.sink.audio
|
color: (AudioService.sink && AudioService.sink.audio && (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0)) ? Qt.rgba(255, 255, 255, 0.5) : "white"
|
||||||
&& (AudioService.sink.audio.muted
|
|
||||||
|| AudioService.sink.audio.volume
|
|
||||||
=== 0)) ? Qt.rgba(255, 255, 255, 0.5) : "white"
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: AudioService.sink && AudioService.sink.audio
|
visible: AudioService.sink && AudioService.sink.audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separator
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 1
|
width: 1
|
||||||
height: 24
|
height: 24
|
||||||
color: Qt.rgba(255, 255, 255, 0.2)
|
color: Qt.rgba(255, 255, 255, 0.2)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: BatteryService.batteryAvailable
|
visible: BatteryService.batteryAvailable && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio))
|
||||||
&& (NetworkService.networkStatus !== "disconnected"
|
|
||||||
|| BluetoothService.enabled
|
|
||||||
|| (AudioService.sink && AudioService.sink.audio))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Battery section
|
|
||||||
Row {
|
Row {
|
||||||
spacing: 4
|
spacing: 4
|
||||||
visible: BatteryService.batteryAvailable
|
visible: BatteryService.batteryAvailable
|
||||||
@@ -701,78 +684,94 @@ Item {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: {
|
name: {
|
||||||
if (BatteryService.isCharging) {
|
if (BatteryService.isCharging) {
|
||||||
if (BatteryService.batteryLevel >= 90)
|
if (BatteryService.batteryLevel >= 90) {
|
||||||
return "battery_charging_full"
|
return "battery_charging_full"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 80)
|
if (BatteryService.batteryLevel >= 80) {
|
||||||
return "battery_charging_90"
|
return "battery_charging_90"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 60)
|
if (BatteryService.batteryLevel >= 60) {
|
||||||
return "battery_charging_80"
|
return "battery_charging_80"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 50)
|
if (BatteryService.batteryLevel >= 50) {
|
||||||
return "battery_charging_60"
|
return "battery_charging_60"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 30)
|
if (BatteryService.batteryLevel >= 30) {
|
||||||
return "battery_charging_50"
|
return "battery_charging_50"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 20)
|
if (BatteryService.batteryLevel >= 20) {
|
||||||
return "battery_charging_30"
|
return "battery_charging_30"
|
||||||
|
}
|
||||||
|
|
||||||
return "battery_charging_20"
|
return "battery_charging_20"
|
||||||
}
|
}
|
||||||
// Check if plugged in but not charging (like at 80% charge limit)
|
|
||||||
if (BatteryService.isPluggedIn) {
|
if (BatteryService.isPluggedIn) {
|
||||||
if (BatteryService.batteryLevel >= 90)
|
if (BatteryService.batteryLevel >= 90) {
|
||||||
return "battery_charging_full"
|
return "battery_charging_full"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 80)
|
if (BatteryService.batteryLevel >= 80) {
|
||||||
return "battery_charging_90"
|
return "battery_charging_90"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 60)
|
if (BatteryService.batteryLevel >= 60) {
|
||||||
return "battery_charging_80"
|
return "battery_charging_80"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 50)
|
if (BatteryService.batteryLevel >= 50) {
|
||||||
return "battery_charging_60"
|
return "battery_charging_60"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 30)
|
if (BatteryService.batteryLevel >= 30) {
|
||||||
return "battery_charging_50"
|
return "battery_charging_50"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 20)
|
if (BatteryService.batteryLevel >= 20) {
|
||||||
return "battery_charging_30"
|
return "battery_charging_30"
|
||||||
|
}
|
||||||
|
|
||||||
return "battery_charging_20"
|
return "battery_charging_20"
|
||||||
}
|
}
|
||||||
// On battery power
|
if (BatteryService.batteryLevel >= 95) {
|
||||||
if (BatteryService.batteryLevel >= 95)
|
|
||||||
return "battery_full"
|
return "battery_full"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 85)
|
if (BatteryService.batteryLevel >= 85) {
|
||||||
return "battery_6_bar"
|
return "battery_6_bar"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 70)
|
if (BatteryService.batteryLevel >= 70) {
|
||||||
return "battery_5_bar"
|
return "battery_5_bar"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 55)
|
if (BatteryService.batteryLevel >= 55) {
|
||||||
return "battery_4_bar"
|
return "battery_4_bar"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 40)
|
if (BatteryService.batteryLevel >= 40) {
|
||||||
return "battery_3_bar"
|
return "battery_3_bar"
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.batteryLevel >= 25)
|
if (BatteryService.batteryLevel >= 25) {
|
||||||
return "battery_2_bar"
|
return "battery_2_bar"
|
||||||
|
}
|
||||||
|
|
||||||
return "battery_1_bar"
|
return "battery_1_bar"
|
||||||
}
|
}
|
||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: {
|
color: {
|
||||||
if (BatteryService.isLowBattery
|
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
|
||||||
&& !BatteryService.isCharging)
|
|
||||||
return Theme.error
|
return Theme.error
|
||||||
|
}
|
||||||
|
|
||||||
if (BatteryService.isCharging
|
if (BatteryService.isCharging || BatteryService.isPluggedIn) {
|
||||||
|| BatteryService.isPluggedIn)
|
|
||||||
return Theme.primary
|
return Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
return "white"
|
return "white"
|
||||||
}
|
}
|
||||||
@@ -800,10 +799,13 @@ Item {
|
|||||||
iconColor: Theme.error
|
iconColor: Theme.error
|
||||||
buttonSize: 40
|
buttonSize: 40
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
console.log("Demo: Power")
|
console.log("Demo: Power")
|
||||||
else
|
} else {
|
||||||
LockScreenService.showPowerDialog()
|
showPowerDialog("Power Off", "Power off this computer?", "Power Off", Theme.error, function() {
|
||||||
|
SessionService.poweroff()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,10 +813,13 @@ Item {
|
|||||||
iconName: "refresh"
|
iconName: "refresh"
|
||||||
buttonSize: 40
|
buttonSize: 40
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
console.log("Demo: Reboot")
|
console.log("Demo: Reboot")
|
||||||
else
|
} else {
|
||||||
LockScreenService.showRebootDialog()
|
showPowerDialog("Restart", "Restart this computer?", "Restart", Theme.primary, function() {
|
||||||
|
SessionService.reboot()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,10 +827,13 @@ Item {
|
|||||||
iconName: "logout"
|
iconName: "logout"
|
||||||
buttonSize: 40
|
buttonSize: 40
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (demoMode)
|
if (demoMode) {
|
||||||
console.log("Demo: Logout")
|
console.log("Demo: Logout")
|
||||||
else
|
} else {
|
||||||
LockScreenService.showLogoutDialog()
|
showPowerDialog("Log Out", "End this session?", "Log Out", Theme.primary, function() {
|
||||||
|
SessionService.logout()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -864,16 +872,14 @@ Item {
|
|||||||
if (!responseRequired)
|
if (!responseRequired)
|
||||||
return
|
return
|
||||||
|
|
||||||
console.log("Responding to PAM with password buffer length:",
|
console.log("Responding to PAM with password buffer length:", root.passwordBuffer.length)
|
||||||
root.passwordBuffer.length)
|
|
||||||
respond(root.passwordBuffer)
|
respond(root.passwordBuffer)
|
||||||
}
|
}
|
||||||
onCompleted: res => {
|
onCompleted: res => {
|
||||||
if (demoMode)
|
if (demoMode)
|
||||||
return
|
return
|
||||||
|
|
||||||
console.log(
|
console.log("PAM authentication completed with result:", res)
|
||||||
"PAM authentication completed with result:", res)
|
|
||||||
if (res === PamResult.Success) {
|
if (res === PamResult.Success) {
|
||||||
console.log("Authentication successful, unlocking")
|
console.log("Authentication successful, unlocking")
|
||||||
LockScreenService.setUnlocking(true)
|
LockScreenService.setUnlocking(true)
|
||||||
@@ -906,20 +912,11 @@ Item {
|
|||||||
onClicked: root.unlockRequested()
|
onClicked: root.unlockRequested()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal power dialog
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: powerDialog
|
|
||||||
|
|
||||||
function open() {
|
|
||||||
LockScreenService.showPowerDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
LockScreenService.hidePowerDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Qt.rgba(0, 0, 0, 0.8)
|
color: Qt.rgba(0, 0, 0, 0.8)
|
||||||
visible: LockScreenService.powerDialogVisible
|
visible: powerDialogVisible
|
||||||
z: 1000
|
z: 1000
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -939,12 +936,12 @@ Item {
|
|||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
name: "power_settings_new"
|
name: "power_settings_new"
|
||||||
size: 32
|
size: 32
|
||||||
color: Theme.error
|
color: powerDialogConfirmColor
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: "Power off this computer?"
|
text: powerDialogMessage
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -958,11 +955,7 @@ Item {
|
|||||||
width: 100
|
width: 100
|
||||||
height: 40
|
height: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: cancelMouse1.pressed ? Qt.rgba(
|
color: Theme.surfaceVariant
|
||||||
Theme.surfaceVariant.r,
|
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
0.7) : cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -972,12 +965,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: cancelMouse1
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: powerDialog.close()
|
onClicked: hidePowerDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -985,249 +976,23 @@ Item {
|
|||||||
width: 100
|
width: 100
|
||||||
height: 40
|
height: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: powerMouse.pressed ? Qt.rgba(
|
color: powerDialogConfirmColor
|
||||||
Theme.error.r,
|
|
||||||
Theme.error.g,
|
|
||||||
Theme.error.b,
|
|
||||||
0.8) : powerMouse.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 1) : Theme.error
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Power Off"
|
text: powerDialogConfirmText
|
||||||
color: "white"
|
color: Theme.primaryText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: powerMouse
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
powerDialog.close()
|
hidePowerDialog()
|
||||||
SessionService.poweroff()
|
powerDialogOnConfirm()
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: rebootDialog
|
|
||||||
|
|
||||||
function open() {
|
|
||||||
LockScreenService.showRebootDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
LockScreenService.hideRebootDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
color: Qt.rgba(0, 0, 0, 0.8)
|
|
||||||
visible: LockScreenService.rebootDialogVisible
|
|
||||||
z: 1000
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 320
|
|
||||||
height: 180
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Theme.surfaceContainer
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXL
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
name: "refresh"
|
|
||||||
size: 32
|
|
||||||
color: Theme.primary
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
text: "Restart this computer?"
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 100
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: cancelMouse2.pressed ? Qt.rgba(
|
|
||||||
Theme.surfaceVariant.r,
|
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
0.7) : cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "Cancel"
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: cancelMouse2
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: rebootDialog.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 100
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: rebootMouse.pressed ? Qt.rgba(
|
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.8) : rebootMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "Restart"
|
|
||||||
color: "white"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: rebootMouse
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
rebootDialog.close()
|
|
||||||
SessionService.reboot()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: logoutDialog
|
|
||||||
|
|
||||||
function open() {
|
|
||||||
LockScreenService.showLogoutDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
LockScreenService.hideLogoutDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
color: Qt.rgba(0, 0, 0, 0.8)
|
|
||||||
visible: LockScreenService.logoutDialogVisible
|
|
||||||
z: 1000
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 320
|
|
||||||
height: 180
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Theme.surfaceContainer
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXL
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
name: "logout"
|
|
||||||
size: 32
|
|
||||||
color: Theme.primary
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
text: "End this session?"
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 100
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: cancelMouse3.pressed ? Qt.rgba(
|
|
||||||
Theme.surfaceVariant.r,
|
|
||||||
Theme.surfaceVariant.g,
|
|
||||||
Theme.surfaceVariant.b,
|
|
||||||
0.7) : cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "Cancel"
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: cancelMouse3
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: logoutDialog.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 100
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: logoutMouse.pressed ? Qt.rgba(
|
|
||||||
Theme.primary.r,
|
|
||||||
Theme.primary.g,
|
|
||||||
Theme.primary.b,
|
|
||||||
0.8) : logoutMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "Log Out"
|
|
||||||
color: "white"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: logoutMouse
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
logoutDialog.close()
|
|
||||||
SessionService.logout()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import QtQuick
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modals.Common
|
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: root
|
id: root
|
||||||
@@ -34,16 +33,11 @@ PanelWindow {
|
|||||||
demoActive = false
|
demoActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmModal {
|
|
||||||
id: powerModal
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: demoActive
|
active: demoActive
|
||||||
sourceComponent: LockScreenContent {
|
sourceComponent: LockScreenContent {
|
||||||
demoMode: true
|
demoMode: true
|
||||||
powerModal: powerModal
|
|
||||||
onUnlockRequested: root.hideDemo()
|
onUnlockRequested: root.hideDemo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modals.Common
|
|
||||||
|
|
||||||
WlSessionLockSurface {
|
WlSessionLockSurface {
|
||||||
id: root
|
id: root
|
||||||
@@ -20,15 +20,10 @@ WlSessionLockSurface {
|
|||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
ConfirmModal {
|
|
||||||
id: powerConfirmModal
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
sourceComponent: LockScreenContent {
|
sourceComponent: LockScreenContent {
|
||||||
demoMode: false
|
demoMode: false
|
||||||
powerModal: powerConfirmModal
|
|
||||||
passwordBuffer: root.sharedPasswordBuffer
|
passwordBuffer: root.sharedPasswordBuffer
|
||||||
onUnlockRequested: root.unlock()
|
onUnlockRequested: root.unlock()
|
||||||
onPasswordBufferChanged: {
|
onPasswordBufferChanged: {
|
||||||
|
|||||||
Reference in New Issue
Block a user