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