mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
dankdash: add wallpaper selector + IPC targets
This commit is contained in:
@@ -49,6 +49,30 @@ Item {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function triggerWallpaperBrowserOnFocusedScreen() {
|
||||||
|
let focusedScreenName = ""
|
||||||
|
if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) {
|
||||||
|
focusedScreenName = Hyprland.focusedWorkspace.monitor.name
|
||||||
|
} else if (CompositorService.isNiri && NiriService.currentOutput) {
|
||||||
|
focusedScreenName = NiriService.currentOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!focusedScreenName && barVariants.instances.length > 0) {
|
||||||
|
const firstBar = barVariants.instances[0]
|
||||||
|
firstBar.triggerWallpaperBrowser()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < barVariants.instances.length; i++) {
|
||||||
|
const barInstance = barVariants.instances[i]
|
||||||
|
if (barInstance.modelData && barInstance.modelData.name === focusedScreenName) {
|
||||||
|
barInstance.triggerWallpaperBrowser()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
id: barVariants
|
id: barVariants
|
||||||
model: SettingsData.getFilteredScreens("dankBar")
|
model: SettingsData.getFilteredScreens("dankBar")
|
||||||
@@ -57,6 +81,7 @@ Item {
|
|||||||
id: barWindow
|
id: barWindow
|
||||||
|
|
||||||
property var controlCenterButtonRef: null
|
property var controlCenterButtonRef: null
|
||||||
|
property var clockButtonRef: null
|
||||||
|
|
||||||
function triggerControlCenter() {
|
function triggerControlCenter() {
|
||||||
controlCenterLoader.active = true
|
controlCenterLoader.active = true
|
||||||
@@ -79,6 +104,27 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function triggerWallpaperBrowser() {
|
||||||
|
dankDashPopoutLoader.active = true
|
||||||
|
if (!dankDashPopoutLoader.item) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clockButtonRef && dankDashPopoutLoader.item.setTriggerPosition) {
|
||||||
|
const globalPos = clockButtonRef.mapToGlobal(0, 0)
|
||||||
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, clockButtonRef.width)
|
||||||
|
const section = clockButtonRef.section || "center"
|
||||||
|
dankDashPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, section, barWindow.screen)
|
||||||
|
} else {
|
||||||
|
dankDashPopoutLoader.item.triggerScreen = barWindow.screen
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dankDashPopoutLoader.item.dashVisible) {
|
||||||
|
dankDashPopoutLoader.item.currentTabIndex = 2
|
||||||
|
}
|
||||||
|
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var dBarLayer: {
|
readonly property var dBarLayer: {
|
||||||
switch (Quickshell.env("DMS_DANKBAR_LAYER")) {
|
switch (Quickshell.env("DMS_DANKBAR_LAYER")) {
|
||||||
case "bottom":
|
case "bottom":
|
||||||
@@ -825,6 +871,17 @@ Item {
|
|||||||
return dankDashPopoutLoader.item
|
return dankDashPopoutLoader.item
|
||||||
}
|
}
|
||||||
parentScreen: barWindow.screen
|
parentScreen: barWindow.screen
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
barWindow.clockButtonRef = this
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (barWindow.clockButtonRef === this) {
|
||||||
|
barWindow.clockButtonRef = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClockClicked: {
|
onClockClicked: {
|
||||||
dankDashPopoutLoader.active = true
|
dankDashPopoutLoader.active = true
|
||||||
if (dankDashPopoutLoader.item) {
|
if (dankDashPopoutLoader.item) {
|
||||||
@@ -874,7 +931,7 @@ Item {
|
|||||||
dankDashPopoutLoader.active = true
|
dankDashPopoutLoader.active = true
|
||||||
if (dankDashPopoutLoader.item) {
|
if (dankDashPopoutLoader.item) {
|
||||||
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
|
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
|
||||||
dankDashPopoutLoader.item.currentTabIndex = 2
|
dankDashPopoutLoader.item.currentTabIndex = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1208,4 +1265,15 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
target: "dankdash"
|
||||||
|
|
||||||
|
function wallpaper(): string {
|
||||||
|
if (root.triggerWallpaperBrowserOnFocusedScreen()) {
|
||||||
|
return "SUCCESS: Toggled wallpaper browser"
|
||||||
|
}
|
||||||
|
return "ERROR: Failed to toggle wallpaper browser"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ DankPopout {
|
|||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
property int currentTabIndex: 0
|
property int currentTabIndex: 0
|
||||||
|
|
||||||
|
keyboardFocusMode: WlrKeyboardFocus.Exclusive
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, screen) {
|
function setTriggerPosition(x, y, width, section, screen) {
|
||||||
triggerSection = section
|
triggerSection = section
|
||||||
triggerScreen = screen
|
triggerScreen = screen
|
||||||
@@ -43,15 +45,49 @@ DankPopout {
|
|||||||
shouldBeVisible: dashVisible
|
shouldBeVisible: dashVisible
|
||||||
visible: shouldBeVisible
|
visible: shouldBeVisible
|
||||||
|
|
||||||
|
property bool __focusArmed: false
|
||||||
|
property bool __contentReady: false
|
||||||
|
|
||||||
|
function __tryFocusOnce() {
|
||||||
|
if (!__focusArmed) return
|
||||||
|
const win = root.window
|
||||||
|
if (!win || !win.visible) return
|
||||||
|
if (!contentLoader.item) return
|
||||||
|
|
||||||
|
if (win.requestActivate) win.requestActivate()
|
||||||
|
contentLoader.item.forceActiveFocus(Qt.TabFocusReason)
|
||||||
|
|
||||||
|
if (contentLoader.item.activeFocus)
|
||||||
|
__focusArmed = false
|
||||||
|
}
|
||||||
|
|
||||||
onDashVisibleChanged: {
|
onDashVisibleChanged: {
|
||||||
if (dashVisible) {
|
if (dashVisible) {
|
||||||
|
__focusArmed = true
|
||||||
|
__contentReady = !!contentLoader.item
|
||||||
open()
|
open()
|
||||||
|
__tryFocusOnce()
|
||||||
} else {
|
} else {
|
||||||
|
__focusArmed = false
|
||||||
|
__contentReady = false
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: contentLoader
|
||||||
|
function onLoaded() {
|
||||||
|
__contentReady = true
|
||||||
|
if (__focusArmed) __tryFocusOnce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.window ? root.window : null
|
||||||
|
enabled: !!root.window
|
||||||
|
function onVisibleChanged() { if (__focusArmed) __tryFocusOnce() }
|
||||||
|
}
|
||||||
|
|
||||||
onBackgroundClicked: {
|
onBackgroundClicked: {
|
||||||
dashVisible = false
|
dashVisible = false
|
||||||
}
|
}
|
||||||
@@ -67,18 +103,12 @@ DankPopout {
|
|||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (root.shouldBeVisible) {
|
if (root.shouldBeVisible) {
|
||||||
forceActiveFocus()
|
mainContainer.forceActiveFocus()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: function(event) {
|
|
||||||
if (event.key === Qt.Key_Escape) {
|
|
||||||
root.dashVisible = false
|
|
||||||
event.accepted = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
target: root
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
if (root.shouldBeVisible) {
|
if (root.shouldBeVisible) {
|
||||||
Qt.callLater(function() {
|
Qt.callLater(function() {
|
||||||
@@ -86,7 +116,52 @@ DankPopout {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target: root
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: function(event) {
|
||||||
|
if (event.key === Qt.Key_Escape) {
|
||||||
|
root.dashVisible = false
|
||||||
|
event.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Tab && !(event.modifiers & Qt.ShiftModifier)) {
|
||||||
|
let nextIndex = root.currentTabIndex + 1
|
||||||
|
while (nextIndex < tabBar.model.length && tabBar.model[nextIndex] && tabBar.model[nextIndex].isAction) {
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
if (nextIndex >= tabBar.model.length) {
|
||||||
|
nextIndex = 0
|
||||||
|
}
|
||||||
|
root.currentTabIndex = nextIndex
|
||||||
|
event.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier))) {
|
||||||
|
let prevIndex = root.currentTabIndex - 1
|
||||||
|
while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
|
||||||
|
prevIndex--
|
||||||
|
}
|
||||||
|
if (prevIndex < 0) {
|
||||||
|
prevIndex = tabBar.model.length - 1
|
||||||
|
while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
|
||||||
|
prevIndex--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prevIndex >= 0) {
|
||||||
|
root.currentTabIndex = prevIndex
|
||||||
|
}
|
||||||
|
event.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.currentTabIndex === 2 && wallpaperTab.handleKeyEvent) {
|
||||||
|
if (wallpaperTab.handleKeyEvent(event)) {
|
||||||
|
event.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -128,11 +203,23 @@ DankPopout {
|
|||||||
currentIndex: root.currentTabIndex
|
currentIndex: root.currentTabIndex
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
equalWidthTabs: true
|
equalWidthTabs: true
|
||||||
|
enableArrowNavigation: false
|
||||||
|
focus: false
|
||||||
|
activeFocusOnTab: false
|
||||||
|
nextFocusTarget: {
|
||||||
|
const item = pages.currentItem
|
||||||
|
if (!item)
|
||||||
|
return null
|
||||||
|
if (item.focusTarget)
|
||||||
|
return item.focusTarget
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
model: {
|
model: {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
{ icon: "dashboard", text: I18n.tr("Overview") },
|
{ icon: "dashboard", text: I18n.tr("Overview") },
|
||||||
{ icon: "music_note", text: I18n.tr("Media") }
|
{ icon: "music_note", text: I18n.tr("Media") },
|
||||||
|
{ icon: "wallpaper", text: I18n.tr("Wallpapers") }
|
||||||
]
|
]
|
||||||
|
|
||||||
if (SettingsData.weatherEnabled) {
|
if (SettingsData.weatherEnabled) {
|
||||||
@@ -148,7 +235,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActionTriggered: function(index) {
|
onActionTriggered: function(index) {
|
||||||
let settingsIndex = SettingsData.weatherEnabled ? 3 : 2
|
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3
|
||||||
if (index === settingsIndex) {
|
if (index === settingsIndex) {
|
||||||
dashVisible = false
|
dashVisible = false
|
||||||
settingsModal.show()
|
settingsModal.show()
|
||||||
@@ -168,7 +255,8 @@ DankPopout {
|
|||||||
implicitHeight: {
|
implicitHeight: {
|
||||||
if (currentIndex === 0) return overviewTab.implicitHeight
|
if (currentIndex === 0) return overviewTab.implicitHeight
|
||||||
if (currentIndex === 1) return mediaTab.implicitHeight
|
if (currentIndex === 1) return mediaTab.implicitHeight
|
||||||
if (SettingsData.weatherEnabled && currentIndex === 2) return weatherTab.implicitHeight
|
if (currentIndex === 2) return wallpaperTab.implicitHeight
|
||||||
|
if (SettingsData.weatherEnabled && currentIndex === 3) return weatherTab.implicitHeight
|
||||||
return overviewTab.implicitHeight
|
return overviewTab.implicitHeight
|
||||||
}
|
}
|
||||||
currentIndex: root.currentTabIndex
|
currentIndex: root.currentTabIndex
|
||||||
@@ -178,8 +266,8 @@ DankPopout {
|
|||||||
|
|
||||||
onSwitchToWeatherTab: {
|
onSwitchToWeatherTab: {
|
||||||
if (SettingsData.weatherEnabled) {
|
if (SettingsData.weatherEnabled) {
|
||||||
tabBar.currentIndex = 2
|
tabBar.currentIndex = 3
|
||||||
tabBar.tabClicked(2)
|
tabBar.tabClicked(3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,9 +281,16 @@ DankPopout {
|
|||||||
id: mediaTab
|
id: mediaTab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WallpaperTab {
|
||||||
|
id: wallpaperTab
|
||||||
|
active: root.currentTabIndex === 2
|
||||||
|
tabBarItem: tabBar
|
||||||
|
keyForwardTarget: mainContainer
|
||||||
|
}
|
||||||
|
|
||||||
WeatherTab {
|
WeatherTab {
|
||||||
id: weatherTab
|
id: weatherTab
|
||||||
visible: SettingsData.weatherEnabled && root.currentTabIndex === 2
|
visible: SettingsData.weatherEnabled && root.currentTabIndex === 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
523
Modules/DankDash/WallpaperTab.qml
Normal file
523
Modules/DankDash/WallpaperTab.qml
Normal file
@@ -0,0 +1,523 @@
|
|||||||
|
import Qt.labs.folderlistmodel
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import qs.Common
|
||||||
|
import qs.Modals.FileBrowser
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
implicitWidth: 700
|
||||||
|
implicitHeight: 410
|
||||||
|
|
||||||
|
property var wallpaperList: []
|
||||||
|
property string wallpaperDir: ""
|
||||||
|
property int currentPage: 0
|
||||||
|
property int itemsPerPage: 16
|
||||||
|
property int totalPages: Math.max(1, Math.ceil(wallpaperList.length / itemsPerPage))
|
||||||
|
property bool active: false
|
||||||
|
property Item focusTarget: wallpaperGrid
|
||||||
|
property Item tabBarItem: null
|
||||||
|
property int gridIndex: 0
|
||||||
|
property Item keyForwardTarget: null
|
||||||
|
property int lastPage: 0
|
||||||
|
property bool enableAnimation: false
|
||||||
|
|
||||||
|
signal requestTabChange(int newIndex)
|
||||||
|
|
||||||
|
onCurrentPageChanged: {
|
||||||
|
if (currentPage !== lastPage) {
|
||||||
|
enableAnimation = false
|
||||||
|
lastPage = currentPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible && active) {
|
||||||
|
setInitialSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
loadWallpapers()
|
||||||
|
if (visible && active) {
|
||||||
|
setInitialSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active && visible) {
|
||||||
|
setInitialSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyEvent(event) {
|
||||||
|
const columns = 4
|
||||||
|
const rows = 4
|
||||||
|
const currentRow = Math.floor(gridIndex / columns)
|
||||||
|
const currentCol = gridIndex % columns
|
||||||
|
const visibleCount = wallpaperGrid.model.length
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||||
|
if (gridIndex >= 0) {
|
||||||
|
const item = wallpaperGrid.currentItem
|
||||||
|
if (item && item.wallpaperPath) {
|
||||||
|
SessionData.setWallpaper(item.wallpaperPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Right) {
|
||||||
|
if (gridIndex + 1 < visibleCount) {
|
||||||
|
// Move right within current page
|
||||||
|
gridIndex++
|
||||||
|
} else if (gridIndex === visibleCount - 1 && currentPage < totalPages - 1) {
|
||||||
|
// At last item in page, go to next page
|
||||||
|
gridIndex = 0
|
||||||
|
currentPage++
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Left) {
|
||||||
|
if (gridIndex > 0) {
|
||||||
|
// Move left within current page
|
||||||
|
gridIndex--
|
||||||
|
} else if (gridIndex === 0 && currentPage > 0) {
|
||||||
|
// At first item in page, go to previous page (last item)
|
||||||
|
currentPage--
|
||||||
|
gridIndex = Math.min(itemsPerPage - 1, wallpaperList.length - currentPage * itemsPerPage - 1)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Down) {
|
||||||
|
if (gridIndex + columns < visibleCount) {
|
||||||
|
// Move down within current page
|
||||||
|
gridIndex += columns
|
||||||
|
} else if (gridIndex >= visibleCount - columns && currentPage < totalPages - 1) {
|
||||||
|
// In last row, go to next page
|
||||||
|
gridIndex = currentCol
|
||||||
|
currentPage++
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Up) {
|
||||||
|
if (gridIndex >= columns) {
|
||||||
|
// Move up within current page
|
||||||
|
gridIndex -= columns
|
||||||
|
} else if (gridIndex < columns && currentPage > 0) {
|
||||||
|
// In first row, go to previous page (last row)
|
||||||
|
currentPage--
|
||||||
|
const prevPageCount = Math.min(itemsPerPage, wallpaperList.length - currentPage * itemsPerPage)
|
||||||
|
const prevPageRows = Math.ceil(prevPageCount / columns)
|
||||||
|
gridIndex = (prevPageRows - 1) * columns + currentCol
|
||||||
|
gridIndex = Math.min(gridIndex, prevPageCount - 1)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_PageUp && currentPage > 0) {
|
||||||
|
gridIndex = 0
|
||||||
|
currentPage--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_PageDown && currentPage < totalPages - 1) {
|
||||||
|
gridIndex = 0
|
||||||
|
currentPage++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Home && event.modifiers & Qt.ControlModifier) {
|
||||||
|
gridIndex = 0
|
||||||
|
currentPage = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_End && event.modifiers & Qt.ControlModifier) {
|
||||||
|
gridIndex = 0
|
||||||
|
currentPage = totalPages - 1
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function setInitialSelection() {
|
||||||
|
if (!SessionData.wallpaperPath) {
|
||||||
|
gridIndex = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const startIndex = currentPage * itemsPerPage
|
||||||
|
const endIndex = Math.min(startIndex + itemsPerPage, wallpaperList.length)
|
||||||
|
const pageWallpapers = wallpaperList.slice(startIndex, endIndex)
|
||||||
|
|
||||||
|
for (let i = 0; i < pageWallpapers.length; i++) {
|
||||||
|
if (pageWallpapers[i] === SessionData.wallpaperPath) {
|
||||||
|
gridIndex = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gridIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
onWallpaperListChanged: {
|
||||||
|
if (visible && active) {
|
||||||
|
setInitialSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadWallpapers() {
|
||||||
|
const currentWallpaper = SessionData.wallpaperPath
|
||||||
|
|
||||||
|
// Try current wallpaper path / fallback to wallpaperLastPath
|
||||||
|
if (!currentWallpaper || currentWallpaper.startsWith("#") || currentWallpaper.startsWith("we:")) {
|
||||||
|
if (CacheData.wallpaperLastPath && CacheData.wallpaperLastPath !== "") {
|
||||||
|
wallpaperDir = CacheData.wallpaperLastPath
|
||||||
|
} else {
|
||||||
|
wallpaperDir = ""
|
||||||
|
wallpaperList = []
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wallpaperDir = currentWallpaper.substring(0, currentWallpaper.lastIndexOf('/'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWallpaperList() {
|
||||||
|
if (!wallpaperFolderModel || wallpaperFolderModel.count === 0) {
|
||||||
|
wallpaperList = []
|
||||||
|
currentPage = 0
|
||||||
|
gridIndex = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build list from FolderListModel
|
||||||
|
const files = []
|
||||||
|
for (let i = 0; i < wallpaperFolderModel.count; i++) {
|
||||||
|
const filePath = wallpaperFolderModel.get(i, "filePath")
|
||||||
|
if (filePath) {
|
||||||
|
// Remove file:// prefix if present
|
||||||
|
const cleanPath = filePath.toString().replace(/^file:\/\//, '')
|
||||||
|
files.push(cleanPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wallpaperList = files
|
||||||
|
|
||||||
|
const currentPath = SessionData.wallpaperPath
|
||||||
|
const selectedIndex = currentPath ? wallpaperList.indexOf(currentPath) : -1
|
||||||
|
|
||||||
|
if (selectedIndex >= 0) {
|
||||||
|
currentPage = Math.floor(selectedIndex / itemsPerPage)
|
||||||
|
gridIndex = selectedIndex % itemsPerPage
|
||||||
|
} else {
|
||||||
|
const maxPage = Math.max(0, Math.ceil(files.length / itemsPerPage) - 1)
|
||||||
|
currentPage = Math.min(Math.max(0, currentPage), maxPage)
|
||||||
|
gridIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SessionData
|
||||||
|
function onWallpaperPathChanged() {
|
||||||
|
loadWallpapers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderListModel {
|
||||||
|
id: wallpaperFolderModel
|
||||||
|
|
||||||
|
showDirsFirst: false
|
||||||
|
showDotAndDotDot: false
|
||||||
|
showHidden: false
|
||||||
|
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
|
||||||
|
showFiles: true
|
||||||
|
showDirs: false
|
||||||
|
sortField: FolderListModel.Name
|
||||||
|
folder: wallpaperDir ? "file://" + wallpaperDir : ""
|
||||||
|
|
||||||
|
onStatusChanged: {
|
||||||
|
if (status === FolderListModel.Ready) {
|
||||||
|
updateWallpaperList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCountChanged: {
|
||||||
|
if (status === FolderListModel.Ready) {
|
||||||
|
updateWallpaperList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: wallpaperBrowserLoader
|
||||||
|
active: false
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
|
sourceComponent: FileBrowserModal {
|
||||||
|
Component.onCompleted: {
|
||||||
|
open()
|
||||||
|
}
|
||||||
|
browserTitle: "Select Wallpaper Directory"
|
||||||
|
browserIcon: "folder_open"
|
||||||
|
browserType: "wallpaper"
|
||||||
|
showHiddenFiles: false
|
||||||
|
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
|
||||||
|
allowStacking: true
|
||||||
|
|
||||||
|
onFileSelected: (path) => {
|
||||||
|
// Set the selected wallpaper
|
||||||
|
const cleanPath = path.replace(/^file:\/\//, '')
|
||||||
|
SessionData.setWallpaper(cleanPath)
|
||||||
|
|
||||||
|
// Extract directory from the selected file and load all wallpapers
|
||||||
|
const dirPath = cleanPath.substring(0, cleanPath.lastIndexOf('/'))
|
||||||
|
if (dirPath) {
|
||||||
|
wallpaperDir = dirPath
|
||||||
|
CacheData.wallpaperLastPath = dirPath
|
||||||
|
CacheData.saveCache()
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
onDialogClosed: {
|
||||||
|
Qt.callLater(() => wallpaperBrowserLoader.active = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height - 50
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: wallpaperGrid
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Theme.spacingS
|
||||||
|
height: parent.height - Theme.spacingS
|
||||||
|
cellWidth: width / 4
|
||||||
|
cellHeight: height / 4
|
||||||
|
clip: true
|
||||||
|
enabled: root.active
|
||||||
|
interactive: root.active
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
keyNavigationEnabled: false
|
||||||
|
activeFocusOnTab: false
|
||||||
|
highlightFollowsCurrentItem: true
|
||||||
|
highlightMoveDuration: enableAnimation ? Theme.shortDuration : 0
|
||||||
|
focus: false
|
||||||
|
|
||||||
|
highlight: Item {
|
||||||
|
z: 1000
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingXS
|
||||||
|
color: "transparent"
|
||||||
|
border.width: 3
|
||||||
|
border.color: Theme.primary
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model: {
|
||||||
|
const startIndex = currentPage * itemsPerPage
|
||||||
|
const endIndex = Math.min(startIndex + itemsPerPage, wallpaperList.length)
|
||||||
|
return wallpaperList.slice(startIndex, endIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
onModelChanged: {
|
||||||
|
const clampedIndex = model.length > 0 ? Math.min(Math.max(0, gridIndex), model.length - 1) : 0
|
||||||
|
if (gridIndex !== clampedIndex) {
|
||||||
|
gridIndex = clampedIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCountChanged: {
|
||||||
|
if (count > 0) {
|
||||||
|
const clampedIndex = Math.min(gridIndex, count - 1)
|
||||||
|
currentIndex = clampedIndex
|
||||||
|
positionViewAtIndex(clampedIndex, GridView.Contain)
|
||||||
|
}
|
||||||
|
enableAnimation = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
function onGridIndexChanged() {
|
||||||
|
if (enableAnimation && wallpaperGrid.count > 0) {
|
||||||
|
wallpaperGrid.currentIndex = gridIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
width: wallpaperGrid.cellWidth
|
||||||
|
height: wallpaperGrid.cellHeight
|
||||||
|
|
||||||
|
property string wallpaperPath: modelData || ""
|
||||||
|
property bool isSelected: SessionData.wallpaperPath === modelData
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: wallpaperCard
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingXS
|
||||||
|
color: Theme.surfaceContainerHighest
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15) : "transparent"
|
||||||
|
radius: parent.radius
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: thumbnailImage
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData ? `file://${modelData}` : ""
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
asynchronous: true
|
||||||
|
cache: true
|
||||||
|
smooth: true
|
||||||
|
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
maskEnabled: true
|
||||||
|
maskThresholdMin: 0.5
|
||||||
|
maskSpreadAtMin: 1.0
|
||||||
|
maskSource: ShaderEffectSource {
|
||||||
|
sourceItem: Rectangle {
|
||||||
|
width: thumbnailImage.width
|
||||||
|
height: thumbnailImage.height
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
running: thumbnailImage.status === Image.Loading
|
||||||
|
visible: running
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
anchors.fill: parent
|
||||||
|
cornerRadius: parent.radius
|
||||||
|
stateColor: Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: wallpaperMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
gridIndex = index
|
||||||
|
if (modelData) {
|
||||||
|
SessionData.setWallpaper(modelData)
|
||||||
|
}
|
||||||
|
// Don't steal focus - let mainContainer keep it for keyboard nav
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: wallpaperList.length === 0
|
||||||
|
text: "No wallpapers found\n\nClick the folder icon below to browse"
|
||||||
|
font.pixelSize: 14
|
||||||
|
color: Theme.outline
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
height: 50
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: (parent.width - controlsRow.width - browseButton.width - Theme.spacingS) / 2
|
||||||
|
height: parent.height
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: controlsRow
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconName: "skip_previous"
|
||||||
|
iconSize: 20
|
||||||
|
buttonSize: 32
|
||||||
|
enabled: currentPage > 0
|
||||||
|
opacity: enabled ? 1.0 : 0.3
|
||||||
|
onClicked: {
|
||||||
|
if (currentPage > 0) {
|
||||||
|
currentPage--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: wallpaperList.length > 0 ? `${wallpaperList.length} wallpapers • ${currentPage + 1} / ${totalPages}` : "No wallpapers"
|
||||||
|
font.pixelSize: 14
|
||||||
|
color: Theme.surfaceText
|
||||||
|
opacity: 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconName: "skip_next"
|
||||||
|
iconSize: 20
|
||||||
|
buttonSize: 32
|
||||||
|
enabled: currentPage < totalPages - 1
|
||||||
|
opacity: enabled ? 1.0 : 0.3
|
||||||
|
onClicked: {
|
||||||
|
if (currentPage < totalPages - 1) {
|
||||||
|
currentPage++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: browseButton
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconName: "folder_open"
|
||||||
|
iconSize: 20
|
||||||
|
buttonSize: 32
|
||||||
|
opacity: 0.7
|
||||||
|
onClicked: wallpaperBrowserLoader.active = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -411,6 +411,9 @@ binds {
|
|||||||
Mod+C hotkey-overlay-title="Control Center" {
|
Mod+C hotkey-overlay-title="Control Center" {
|
||||||
spawn "dms" "ipc" "call" "control-center" "toggle";
|
spawn "dms" "ipc" "call" "control-center" "toggle";
|
||||||
}
|
}
|
||||||
|
Mod+Y hotkey-overlay-title="Browse Wallpapers" {
|
||||||
|
spawn "dms" "ipc" "call" "dankdash" "wallpaper";
|
||||||
|
}
|
||||||
XF86AudioRaiseVolume allow-when-locked=true {
|
XF86AudioRaiseVolume allow-when-locked=true {
|
||||||
spawn "dms" "ipc" "call" "audio" "increment" "3";
|
spawn "dms" "ipc" "call" "audio" "increment" "3";
|
||||||
}
|
}
|
||||||
@@ -478,6 +481,7 @@ bind = SUPER, comma, exec, dms ipc call settings toggle
|
|||||||
bind = SUPER, P, exec, dms ipc call notepad toggle
|
bind = SUPER, P, exec, dms ipc call notepad toggle
|
||||||
bind = SUPERALT, L, exec, dms ipc call lock lock
|
bind = SUPERALT, L, exec, dms ipc call lock lock
|
||||||
bind = SUPER, X, exec, dms ipc call powermenu toggle
|
bind = SUPER, X, exec, dms ipc call powermenu toggle
|
||||||
|
bind = SUPER, Y, exec, dms ipc call dankdash wallpaper
|
||||||
bind = SUPER, C, exec, dms ipc call control-center toggle
|
bind = SUPER, C, exec, dms ipc call control-center toggle
|
||||||
bind = SUPER, TAB, exec, dms ipc call hypr toggleOverview
|
bind = SUPER, TAB, exec, dms ipc call hypr toggleOverview
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ binds {
|
|||||||
spawn "dms" "ipc" "call" "notifications" "toggle";
|
spawn "dms" "ipc" "call" "notifications" "toggle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mod+Y hotkey-overlay-title="Browse Wallpapers" {
|
||||||
|
spawn "dms" "ipc" "call" "dankdash" "wallpaper";
|
||||||
|
}
|
||||||
|
|
||||||
Mod+Shift+N hotkey-overlay-title="Notepad" {
|
Mod+Shift+N hotkey-overlay-title="Notepad" {
|
||||||
spawn "dms" "ipc" "call" "notepad" "toggle";
|
spawn "dms" "ipc" "call" "notepad" "toggle";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ PanelWindow {
|
|||||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
|
property int keyboardFocusMode: WlrKeyboardFocus.OnDemand
|
||||||
|
|
||||||
signal opened
|
signal opened
|
||||||
signal popoutClosed
|
signal popoutClosed
|
||||||
@@ -63,7 +64,7 @@ PanelWindow {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
WlrLayershell.layer: WlrLayershell.Top
|
WlrLayershell.layer: WlrLayershell.Top
|
||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
WlrLayershell.keyboardFocus: shouldBeVisible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: shouldBeVisible ? keyboardFocusMode : WlrKeyboardFocus.None
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
top: true
|
top: true
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import QtQuick
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
FocusScope {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
|
|
||||||
property alias model: tabRepeater.model
|
property alias model: tabRepeater.model
|
||||||
@@ -11,12 +11,101 @@ Item {
|
|||||||
property int tabHeight: 56
|
property int tabHeight: 56
|
||||||
property bool showIcons: true
|
property bool showIcons: true
|
||||||
property bool equalWidthTabs: true
|
property bool equalWidthTabs: true
|
||||||
|
property bool enableArrowNavigation: true
|
||||||
|
property Item nextFocusTarget: null
|
||||||
|
property Item previousFocusTarget: null
|
||||||
|
|
||||||
signal tabClicked(int index)
|
signal tabClicked(int index)
|
||||||
signal actionTriggered(int index)
|
signal actionTriggered(int index)
|
||||||
|
|
||||||
|
focus: false
|
||||||
|
activeFocusOnTab: true
|
||||||
height: tabHeight
|
height: tabHeight
|
||||||
|
|
||||||
|
KeyNavigation.tab: nextFocusTarget
|
||||||
|
KeyNavigation.down: nextFocusTarget
|
||||||
|
KeyNavigation.backtab: previousFocusTarget
|
||||||
|
KeyNavigation.up: previousFocusTarget
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
if (!tabBar.activeFocus || tabRepeater.count === 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
function findSelectableIndex(startIndex, step) {
|
||||||
|
let idx = startIndex
|
||||||
|
for (let i = 0; i < tabRepeater.count; i++) {
|
||||||
|
idx = (idx + step + tabRepeater.count) % tabRepeater.count
|
||||||
|
const item = tabRepeater.itemAt(idx)
|
||||||
|
if (item && !item.isAction)
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const goToIndex = (nextIndex) => {
|
||||||
|
if (nextIndex >= 0 && nextIndex !== tabBar.currentIndex) {
|
||||||
|
tabBar.currentIndex = nextIndex
|
||||||
|
tabBar.tabClicked(nextIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveTarget = (item) => {
|
||||||
|
if (!item)
|
||||||
|
return null
|
||||||
|
|
||||||
|
if (item.focusTarget)
|
||||||
|
return resolveTarget(item.focusTarget)
|
||||||
|
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
const focusItem = (item) => {
|
||||||
|
const target = resolveTarget(item)
|
||||||
|
if (!target)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (target.requestFocus) {
|
||||||
|
Qt.callLater(() => target.requestFocus())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.forceActiveFocus) {
|
||||||
|
Qt.callLater(() => target.forceActiveFocus())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Right && tabBar.enableArrowNavigation) {
|
||||||
|
const baseIndex = (tabBar.currentIndex >= 0 && tabBar.currentIndex < tabRepeater.count) ? tabBar.currentIndex : -1
|
||||||
|
const nextIndex = findSelectableIndex(baseIndex, 1)
|
||||||
|
if (nextIndex >= 0) {
|
||||||
|
goToIndex(nextIndex)
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_Left && tabBar.enableArrowNavigation) {
|
||||||
|
const baseIndex = (tabBar.currentIndex >= 0 && tabBar.currentIndex < tabRepeater.count) ? tabBar.currentIndex : 0
|
||||||
|
const nextIndex = findSelectableIndex(baseIndex, -1)
|
||||||
|
if (nextIndex >= 0) {
|
||||||
|
goToIndex(nextIndex)
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier)) {
|
||||||
|
if (focusItem(tabBar.previousFocusTarget)) {
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down) {
|
||||||
|
if (focusItem(tabBar.nextFocusTarget)) {
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_Up) {
|
||||||
|
if (focusItem(tabBar.previousFocusTarget)) {
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: tabRow
|
id: tabRow
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -77,7 +166,6 @@ Item {
|
|||||||
if (tabItem.isAction) {
|
if (tabItem.isAction) {
|
||||||
tabBar.actionTriggered(index)
|
tabBar.actionTriggered(index)
|
||||||
} else {
|
} else {
|
||||||
tabBar.currentIndex = index
|
|
||||||
tabBar.tabClicked(index)
|
tabBar.tabClicked(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
docs/IPC.md
10
docs/IPC.md
@@ -501,6 +501,13 @@ Dashboard popup control with tab selection for overview, media, and weather info
|
|||||||
- Parameters: `tab` - Optional tab to open when showing: "" (default), "overview", "media", or "weather"
|
- Parameters: `tab` - Optional tab to open when showing: "" (default), "overview", "media", or "weather"
|
||||||
- Returns: Success/failure message
|
- Returns: Success/failure message
|
||||||
|
|
||||||
|
### Target: `dankdash`
|
||||||
|
DankDash wallpaper browser control.
|
||||||
|
|
||||||
|
**Functions:**
|
||||||
|
- `wallpaper` - Toggle DankDash popup on focused screen with wallpaper tab selected
|
||||||
|
- Returns: Success/failure message
|
||||||
|
|
||||||
### Target: `file`
|
### Target: `file`
|
||||||
File browser controls for selecting wallpapers and profile images.
|
File browser controls for selecting wallpapers and profile images.
|
||||||
|
|
||||||
@@ -581,6 +588,9 @@ dms ipc call dash open overview
|
|||||||
dms ipc call dash toggle media
|
dms ipc call dash toggle media
|
||||||
dms ipc call dash open weather
|
dms ipc call dash open weather
|
||||||
|
|
||||||
|
# Open wallpaper browser
|
||||||
|
dms ipc call dankdash wallpaper
|
||||||
|
|
||||||
# Open file browsers
|
# Open file browsers
|
||||||
dms ipc call file browse wallpaper
|
dms ipc call file browse wallpaper
|
||||||
dms ipc call file browse profile
|
dms ipc call file browse profile
|
||||||
|
|||||||
Reference in New Issue
Block a user