mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
launcher: consistent spacing of grid mode
This commit is contained in:
@@ -152,7 +152,7 @@ Item {
|
|||||||
if (searchMode === "apps" && appLauncher.model.count > 0) {
|
if (searchMode === "apps" && appLauncher.model.count > 0) {
|
||||||
const selectedApp = appLauncher.model.get(appLauncher.selectedIndex);
|
const selectedApp = appLauncher.model.get(appLauncher.selectedIndex);
|
||||||
const menu = usePopupContextMenu ? popupContextMenu : layerContextMenuLoader.item;
|
const menu = usePopupContextMenu ? popupContextMenu : layerContextMenuLoader.item;
|
||||||
|
|
||||||
if (selectedApp && menu && resultsView) {
|
if (selectedApp && menu && resultsView) {
|
||||||
const itemPos = resultsView.getSelectedItemPosition();
|
const itemPos = resultsView.getSelectedItemPosition();
|
||||||
const contentPos = resultsView.mapToItem(spotlightKeyHandler, itemPos.x, itemPos.y);
|
const contentPos = resultsView.mapToItem(spotlightKeyHandler, itemPos.x, itemPos.y);
|
||||||
@@ -192,10 +192,9 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SpotlightContextMenuPopup {
|
SpotlightContextMenuPopup {
|
||||||
id: popupContextMenu
|
id: popupContextMenu
|
||||||
|
|
||||||
parent: spotlightKeyHandler
|
parent: spotlightKeyHandler
|
||||||
appLauncher: spotlightKeyHandler.appLauncher
|
appLauncher: spotlightKeyHandler.appLauncher
|
||||||
parentHandler: spotlightKeyHandler
|
parentHandler: spotlightKeyHandler
|
||||||
@@ -203,7 +202,7 @@ Item {
|
|||||||
visible: false
|
visible: false
|
||||||
z: 1000
|
z: 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: usePopupContextMenu && popupContextMenu.visible
|
visible: usePopupContextMenu && popupContextMenu.visible
|
||||||
@@ -211,7 +210,7 @@ Item {
|
|||||||
z: 999
|
z: 999
|
||||||
onClicked: popupContextMenu.hide()
|
onClicked: popupContextMenu.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: layerContextMenuLoader
|
id: layerContextMenuLoader
|
||||||
active: !spotlightKeyHandler.usePopupContextMenu
|
active: !spotlightKeyHandler.usePopupContextMenu
|
||||||
@@ -224,7 +223,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: parentModal
|
target: parentModal
|
||||||
function onSpotlightOpenChanged() {
|
function onSpotlightOpenChanged() {
|
||||||
@@ -244,16 +243,17 @@ Item {
|
|||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
clip: false
|
clip: false
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
width: parent.width
|
id: searchRow
|
||||||
spacing: Theme.spacingM
|
width: parent.width - Theme.spacingS * 2
|
||||||
leftPadding: Theme.spacingS
|
height: 56
|
||||||
topPadding: Theme.spacingS
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
DankTextField {
|
DankTextField {
|
||||||
id: searchField
|
id: searchField
|
||||||
|
anchors.left: parent.left
|
||||||
width: parent.width - 80 - Theme.spacingL
|
anchors.right: buttonsContainer.left
|
||||||
|
anchors.rightMargin: Theme.spacingM
|
||||||
height: 56
|
height: 56
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||||
@@ -302,147 +302,159 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
spacing: Theme.spacingXS
|
id: buttonsContainer
|
||||||
visible: searchMode === "apps" && appLauncher.model.count > 0
|
width: viewModeButtons.visible ? viewModeButtons.width : (fileSearchButtons.visible ? fileSearchButtons.width : 0)
|
||||||
|
height: 36
|
||||||
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
Rectangle {
|
Row {
|
||||||
width: 36
|
id: viewModeButtons
|
||||||
height: 36
|
spacing: Theme.spacingXS
|
||||||
radius: Theme.cornerRadius
|
visible: searchMode === "apps" && appLauncher.model.count > 0
|
||||||
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
DankIcon {
|
Rectangle {
|
||||||
anchors.centerIn: parent
|
width: 36
|
||||||
name: "view_list"
|
height: 36
|
||||||
size: 18
|
radius: Theme.cornerRadius
|
||||||
color: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
|
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "view_list"
|
||||||
|
size: 18
|
||||||
|
color: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: listViewArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
appLauncher.setViewMode("list");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Rectangle {
|
||||||
id: listViewArea
|
width: 36
|
||||||
|
height: 36
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
|
||||||
anchors.fill: parent
|
DankIcon {
|
||||||
hoverEnabled: true
|
anchors.centerIn: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
name: "grid_view"
|
||||||
onClicked: () => {
|
size: 18
|
||||||
appLauncher.setViewMode("list");
|
color: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: gridViewArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
appLauncher.setViewMode("grid");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Row {
|
||||||
width: 36
|
id: fileSearchButtons
|
||||||
height: 36
|
spacing: Theme.spacingXS
|
||||||
radius: Theme.cornerRadius
|
visible: searchMode === "files"
|
||||||
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
DankIcon {
|
Rectangle {
|
||||||
anchors.centerIn: parent
|
id: filenameFilterButton
|
||||||
name: "grid_view"
|
|
||||||
size: 18
|
|
||||||
color: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
width: 36
|
||||||
id: gridViewArea
|
height: 36
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: fileSearchController.searchField === "filename" ? Theme.primaryHover : filenameFilterArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
|
||||||
anchors.fill: parent
|
DankIcon {
|
||||||
hoverEnabled: true
|
anchors.centerIn: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
name: "title"
|
||||||
onClicked: () => {
|
size: 18
|
||||||
appLauncher.setViewMode("grid");
|
color: fileSearchController.searchField === "filename" ? Theme.primary : Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: filenameFilterArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
fileSearchController.searchField = "filename";
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
filenameTooltipLoader.active = true;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (filenameTooltipLoader.item) {
|
||||||
|
const p = mapToItem(null, width / 2, height + Theme.spacingXS);
|
||||||
|
filenameTooltipLoader.item.show(I18n.tr("Search filenames"), p.x, p.y, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
if (filenameTooltipLoader.item)
|
||||||
|
filenameTooltipLoader.item.hide();
|
||||||
|
|
||||||
|
filenameTooltipLoader.active = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
Rectangle {
|
||||||
spacing: Theme.spacingXS
|
id: contentFilterButton
|
||||||
visible: searchMode === "files"
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
Rectangle {
|
width: 36
|
||||||
id: filenameFilterButton
|
height: 36
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: fileSearchController.searchField === "body" ? Theme.primaryHover : contentFilterArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
|
||||||
width: 36
|
DankIcon {
|
||||||
height: 36
|
anchors.centerIn: parent
|
||||||
radius: Theme.cornerRadius
|
name: "description"
|
||||||
color: fileSearchController.searchField === "filename" ? Theme.primaryHover : filenameFilterArea.containsMouse ? Theme.surfaceHover : "transparent"
|
size: 18
|
||||||
|
color: fileSearchController.searchField === "body" ? Theme.primary : Theme.surfaceText
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "title"
|
|
||||||
size: 18
|
|
||||||
color: fileSearchController.searchField === "filename" ? Theme.primary : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: filenameFilterArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: () => {
|
|
||||||
fileSearchController.searchField = "filename";
|
|
||||||
}
|
}
|
||||||
onEntered: {
|
|
||||||
filenameTooltipLoader.active = true;
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (filenameTooltipLoader.item) {
|
|
||||||
const p = mapToItem(null, width / 2, height + Theme.spacingXS);
|
|
||||||
filenameTooltipLoader.item.show(I18n.tr("Search filenames"), p.x, p.y, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
if (filenameTooltipLoader.item)
|
|
||||||
filenameTooltipLoader.item.hide();
|
|
||||||
|
|
||||||
filenameTooltipLoader.active = false;
|
MouseArea {
|
||||||
}
|
id: contentFilterArea
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
anchors.fill: parent
|
||||||
id: contentFilterButton
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
fileSearchController.searchField = "body";
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
contentTooltipLoader.active = true;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (contentTooltipLoader.item) {
|
||||||
|
const p = mapToItem(null, width / 2, height + Theme.spacingXS);
|
||||||
|
contentTooltipLoader.item.show(I18n.tr("Search file contents"), p.x, p.y, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
if (contentTooltipLoader.item)
|
||||||
|
contentTooltipLoader.item.hide();
|
||||||
|
|
||||||
width: 36
|
contentTooltipLoader.active = false;
|
||||||
height: 36
|
}
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: fileSearchController.searchField === "body" ? Theme.primaryHover : contentFilterArea.containsMouse ? Theme.surfaceHover : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "description"
|
|
||||||
size: 18
|
|
||||||
color: fileSearchController.searchField === "body" ? Theme.primary : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: contentFilterArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: () => {
|
|
||||||
fileSearchController.searchField = "body";
|
|
||||||
}
|
|
||||||
onEntered: {
|
|
||||||
contentTooltipLoader.active = true;
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (contentTooltipLoader.item) {
|
|
||||||
const p = mapToItem(null, width / 2, height + Theme.spacingXS);
|
|
||||||
contentTooltipLoader.item.show(I18n.tr("Search file contents"), p.x, p.y, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
if (contentTooltipLoader.item)
|
|
||||||
contentTooltipLoader.item.hide();
|
|
||||||
|
|
||||||
contentTooltipLoader.active = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,13 +470,13 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
appLauncher: spotlightKeyHandler.appLauncher
|
appLauncher: spotlightKeyHandler.appLauncher
|
||||||
visible: searchMode === "apps"
|
visible: searchMode === "apps"
|
||||||
|
|
||||||
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
||||||
const menu = usePopupContextMenu ? popupContextMenu : layerContextMenuLoader.item;
|
const menu = usePopupContextMenu ? popupContextMenu : layerContextMenuLoader.item;
|
||||||
|
|
||||||
if (menu?.show) {
|
if (menu?.show) {
|
||||||
const isPopup = menu.contentItem !== undefined;
|
const isPopup = menu.contentItem !== undefined;
|
||||||
|
|
||||||
if (isPopup) {
|
if (isPopup) {
|
||||||
const localPos = popupContextMenu.parent.mapFromItem(null, mouseX, mouseY);
|
const localPos = popupContextMenu.parent.mapFromItem(null, mouseX, mouseY);
|
||||||
menu.show(localPos.x, localPos.y, modelData, false);
|
menu.show(localPos.x, localPos.y, modelData, false);
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -8,32 +6,45 @@ Rectangle {
|
|||||||
id: resultsContainer
|
id: resultsContainer
|
||||||
|
|
||||||
property var appLauncher: null
|
property var appLauncher: null
|
||||||
|
|
||||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||||
|
|
||||||
function resetScroll() {
|
function resetScroll() {
|
||||||
resultsList.contentY = 0
|
resultsList.contentY = 0;
|
||||||
if (gridLoader.item) {
|
if (gridLoader.item) {
|
||||||
gridLoader.item.contentY = 0
|
gridLoader.item.contentY = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedItemPosition() {
|
function getSelectedItemPosition() {
|
||||||
if (!appLauncher) return { x: 0, y: 0 };
|
if (!appLauncher)
|
||||||
|
return {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
|
|
||||||
const selectedIndex = appLauncher.selectedIndex;
|
const selectedIndex = appLauncher.selectedIndex;
|
||||||
if (appLauncher.viewMode === "list") {
|
if (appLauncher.viewMode === "list") {
|
||||||
const itemY = selectedIndex * (resultsList.itemHeight + resultsList.itemSpacing) - resultsList.contentY;
|
const itemY = selectedIndex * (resultsList.itemHeight + resultsList.itemSpacing) - resultsList.contentY;
|
||||||
return { x: resultsList.width / 2, y: itemY + resultsList.itemHeight / 2 };
|
return {
|
||||||
|
x: resultsList.width / 2,
|
||||||
|
y: itemY + resultsList.itemHeight / 2
|
||||||
|
};
|
||||||
} else if (gridLoader.item) {
|
} else if (gridLoader.item) {
|
||||||
const grid = gridLoader.item;
|
const grid = gridLoader.item;
|
||||||
const row = Math.floor(selectedIndex / grid.actualColumns);
|
const row = Math.floor(selectedIndex / grid.actualColumns);
|
||||||
const col = selectedIndex % grid.actualColumns;
|
const col = selectedIndex % grid.actualColumns;
|
||||||
const itemX = col * grid.cellWidth + grid.leftMargin + grid.cellWidth / 2;
|
const itemX = col * grid.cellWidth + grid.leftMargin + grid.cellWidth / 2;
|
||||||
const itemY = row * grid.cellHeight - grid.contentY + grid.cellHeight / 2;
|
const itemY = row * grid.cellHeight - grid.contentY + grid.cellHeight / 2;
|
||||||
return { x: itemX, y: itemY };
|
return {
|
||||||
|
x: itemX,
|
||||||
|
y: itemY
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return { x: 0, y: 0 };
|
return {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
@@ -56,14 +67,13 @@ Rectangle {
|
|||||||
|
|
||||||
function ensureVisible(index) {
|
function ensureVisible(index) {
|
||||||
if (index < 0 || index >= count)
|
if (index < 0 || index >= count)
|
||||||
return
|
return;
|
||||||
|
const itemY = index * (itemHeight + itemSpacing);
|
||||||
const itemY = index * (itemHeight + itemSpacing)
|
const itemBottom = itemY + itemHeight;
|
||||||
const itemBottom = itemY + itemHeight
|
|
||||||
if (itemY < contentY)
|
if (itemY < contentY)
|
||||||
contentY = itemY
|
contentY = itemY;
|
||||||
else if (itemBottom > contentY + height)
|
else if (itemBottom > contentY + height)
|
||||||
contentY = itemBottom - height
|
contentY = itemBottom - height;
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -79,19 +89,19 @@ Rectangle {
|
|||||||
reuseItems: true
|
reuseItems: true
|
||||||
onCurrentIndexChanged: {
|
onCurrentIndexChanged: {
|
||||||
if (keyboardNavigationActive)
|
if (keyboardNavigationActive)
|
||||||
ensureVisible(currentIndex)
|
ensureVisible(currentIndex);
|
||||||
}
|
}
|
||||||
onItemClicked: (index, modelData) => {
|
onItemClicked: (index, modelData) => {
|
||||||
if (appLauncher)
|
if (appLauncher)
|
||||||
appLauncher.launchApp(modelData)
|
appLauncher.launchApp(modelData);
|
||||||
}
|
}
|
||||||
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
||||||
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
onKeyboardNavigationReset: () => {
|
onKeyboardNavigationReset: () => {
|
||||||
if (appLauncher)
|
if (appLauncher)
|
||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: AppLauncherListDelegate {
|
delegate: AppLauncherListDelegate {
|
||||||
listView: resultsList
|
listView: resultsList
|
||||||
@@ -105,7 +115,7 @@ Rectangle {
|
|||||||
iconUnicodeScale: 0.8
|
iconUnicodeScale: 0.8
|
||||||
onItemClicked: (idx, modelData) => resultsList.itemClicked(idx, modelData)
|
onItemClicked: (idx, modelData) => resultsList.itemClicked(idx, modelData)
|
||||||
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
resultsList.itemRightClicked(idx, modelData, mouseX, mouseY)
|
resultsList.itemRightClicked(idx, modelData, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
onKeyboardNavigationReset: resultsList.keyboardNavigationReset
|
onKeyboardNavigationReset: resultsList.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
@@ -121,20 +131,20 @@ Rectangle {
|
|||||||
visible: appLauncher && appLauncher.viewMode === "grid"
|
visible: appLauncher && appLauncher.viewMode === "grid"
|
||||||
active: appLauncher && appLauncher.viewMode === "grid"
|
active: appLauncher && appLauncher.viewMode === "grid"
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (item) {
|
if (item) {
|
||||||
item.appLauncher = Qt.binding(() => resultsContainer.appLauncher);
|
item.appLauncher = Qt.binding(() => resultsContainer.appLauncher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onWidthChanged: {
|
onWidthChanged: {
|
||||||
if (visible && Math.abs(width - _lastWidth) > 1) {
|
if (visible && Math.abs(width - _lastWidth) > 1) {
|
||||||
_lastWidth = width
|
_lastWidth = width;
|
||||||
active = false
|
active = false;
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
active = true
|
active = true;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
@@ -148,14 +158,13 @@ Rectangle {
|
|||||||
property bool adaptiveColumns: false
|
property bool adaptiveColumns: false
|
||||||
property int minCellWidth: 120
|
property int minCellWidth: 120
|
||||||
property int maxCellWidth: 160
|
property int maxCellWidth: 160
|
||||||
property int cellPadding: 8
|
|
||||||
property real iconSizeRatio: 0.55
|
property real iconSizeRatio: 0.55
|
||||||
property int maxIconSize: 48
|
property int maxIconSize: 48
|
||||||
property int minIconSize: 32
|
property int minIconSize: 32
|
||||||
property bool hoverUpdatesSelection: false
|
property bool hoverUpdatesSelection: false
|
||||||
property bool keyboardNavigationActive: appLauncher ? appLauncher.keyboardNavigationActive : false
|
property bool keyboardNavigationActive: appLauncher ? appLauncher.keyboardNavigationActive : false
|
||||||
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
property real baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : width / columns
|
||||||
property int baseCellHeight: baseCellWidth + 20
|
property real baseCellHeight: baseCellWidth + 20
|
||||||
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
||||||
property int remainingSpace: width - (actualColumns * cellWidth)
|
property int remainingSpace: width - (actualColumns * cellWidth)
|
||||||
|
|
||||||
@@ -165,47 +174,44 @@ Rectangle {
|
|||||||
|
|
||||||
function ensureVisible(index) {
|
function ensureVisible(index) {
|
||||||
if (index < 0 || index >= count)
|
if (index < 0 || index >= count)
|
||||||
return
|
return;
|
||||||
|
const itemY = Math.floor(index / actualColumns) * cellHeight;
|
||||||
const itemY = Math.floor(index / actualColumns) * cellHeight
|
const itemBottom = itemY + cellHeight;
|
||||||
const itemBottom = itemY + cellHeight
|
|
||||||
if (itemY < contentY)
|
if (itemY < contentY)
|
||||||
contentY = itemY
|
contentY = itemY;
|
||||||
else if (itemBottom > contentY + height)
|
else if (itemBottom > contentY + height)
|
||||||
contentY = itemBottom - height
|
contentY = itemBottom - height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
model: appLauncher ? appLauncher.model : null
|
model: appLauncher ? appLauncher.model : null
|
||||||
clip: true
|
clip: true
|
||||||
cellWidth: baseCellWidth
|
cellWidth: baseCellWidth
|
||||||
cellHeight: baseCellHeight
|
cellHeight: baseCellHeight
|
||||||
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
|
|
||||||
rightMargin: leftMargin
|
|
||||||
focus: true
|
focus: true
|
||||||
interactive: true
|
interactive: true
|
||||||
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
||||||
reuseItems: true
|
reuseItems: true
|
||||||
onCurrentIndexChanged: {
|
onCurrentIndexChanged: {
|
||||||
if (keyboardNavigationActive)
|
if (keyboardNavigationActive)
|
||||||
ensureVisible(currentIndex)
|
ensureVisible(currentIndex);
|
||||||
}
|
}
|
||||||
onItemClicked: (index, modelData) => {
|
onItemClicked: (index, modelData) => {
|
||||||
if (appLauncher)
|
if (appLauncher)
|
||||||
appLauncher.launchApp(modelData)
|
appLauncher.launchApp(modelData);
|
||||||
}
|
}
|
||||||
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
||||||
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
onKeyboardNavigationReset: () => {
|
onKeyboardNavigationReset: () => {
|
||||||
if (appLauncher)
|
if (appLauncher)
|
||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: AppLauncherGridDelegate {
|
delegate: AppLauncherGridDelegate {
|
||||||
gridView: resultsGrid
|
gridView: resultsGrid
|
||||||
cellWidth: resultsGrid.cellWidth
|
cellWidth: resultsGrid.cellWidth
|
||||||
cellHeight: resultsGrid.cellHeight
|
cellHeight: resultsGrid.cellHeight
|
||||||
cellPadding: resultsGrid.cellPadding
|
|
||||||
minIconSize: resultsGrid.minIconSize
|
minIconSize: resultsGrid.minIconSize
|
||||||
maxIconSize: resultsGrid.maxIconSize
|
maxIconSize: resultsGrid.maxIconSize
|
||||||
iconSizeRatio: resultsGrid.iconSizeRatio
|
iconSizeRatio: resultsGrid.iconSizeRatio
|
||||||
@@ -214,7 +220,7 @@ Rectangle {
|
|||||||
currentIndex: resultsGrid.currentIndex
|
currentIndex: resultsGrid.currentIndex
|
||||||
onItemClicked: (idx, modelData) => resultsGrid.itemClicked(idx, modelData)
|
onItemClicked: (idx, modelData) => resultsGrid.itemClicked(idx, modelData)
|
||||||
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
resultsGrid.itemRightClicked(idx, modelData, mouseX, mouseY)
|
resultsGrid.itemRightClicked(idx, modelData, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
onKeyboardNavigationReset: resultsGrid.keyboardNavigationReset
|
onKeyboardNavigationReset: resultsGrid.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,18 +252,19 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
width: parent.width
|
width: parent.width - Theme.spacingS * 2
|
||||||
height: 40
|
height: 40
|
||||||
spacing: Theme.spacingM
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: searchField.text.length === 0
|
visible: searchField.text.length === 0
|
||||||
leftPadding: Theme.spacingS
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 180
|
width: 180
|
||||||
height: 40
|
height: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
DankDropdown {
|
DankDropdown {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -278,13 +279,9 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width - 290
|
|
||||||
height: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
@@ -314,7 +311,8 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: searchField.width
|
||||||
|
x: searchField.x
|
||||||
height: {
|
height: {
|
||||||
let usedHeight = 40 + Theme.spacingS;
|
let usedHeight = 40 + Theme.spacingS;
|
||||||
usedHeight += 52 + Theme.spacingS;
|
usedHeight += 52 + Theme.spacingS;
|
||||||
@@ -350,8 +348,6 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
anchors.bottomMargin: Theme.spacingS
|
||||||
visible: appLauncher.viewMode === "list"
|
visible: appLauncher.viewMode === "list"
|
||||||
model: appLauncher.model
|
model: appLauncher.model
|
||||||
@@ -410,14 +406,13 @@ DankPopout {
|
|||||||
property bool adaptiveColumns: false
|
property bool adaptiveColumns: false
|
||||||
property int minCellWidth: 120
|
property int minCellWidth: 120
|
||||||
property int maxCellWidth: 160
|
property int maxCellWidth: 160
|
||||||
property int cellPadding: 8
|
|
||||||
property real iconSizeRatio: 0.6
|
property real iconSizeRatio: 0.6
|
||||||
property int maxIconSize: 56
|
property int maxIconSize: 56
|
||||||
property int minIconSize: 32
|
property int minIconSize: 32
|
||||||
property bool hoverUpdatesSelection: false
|
property bool hoverUpdatesSelection: false
|
||||||
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
|
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
|
||||||
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
property real baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : width / columns
|
||||||
property int baseCellHeight: baseCellWidth + 20
|
property real baseCellHeight: baseCellWidth + 20
|
||||||
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
||||||
|
|
||||||
property int remainingSpace: width - (actualColumns * cellWidth)
|
property int remainingSpace: width - (actualColumns * cellWidth)
|
||||||
@@ -438,16 +433,12 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
anchors.bottomMargin: Theme.spacingS
|
||||||
visible: appLauncher.viewMode === "grid"
|
visible: appLauncher.viewMode === "grid"
|
||||||
model: appLauncher.model
|
model: appLauncher.model
|
||||||
clip: true
|
clip: true
|
||||||
cellWidth: baseCellWidth
|
cellWidth: baseCellWidth
|
||||||
cellHeight: baseCellHeight
|
cellHeight: baseCellHeight
|
||||||
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
|
|
||||||
rightMargin: leftMargin
|
|
||||||
focus: true
|
focus: true
|
||||||
interactive: true
|
interactive: true
|
||||||
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
||||||
@@ -472,7 +463,6 @@ DankPopout {
|
|||||||
gridView: appGrid
|
gridView: appGrid
|
||||||
cellWidth: appGrid.cellWidth
|
cellWidth: appGrid.cellWidth
|
||||||
cellHeight: appGrid.cellHeight
|
cellHeight: appGrid.cellHeight
|
||||||
cellPadding: appGrid.cellPadding
|
|
||||||
minIconSize: appGrid.minIconSize
|
minIconSize: appGrid.minIconSize
|
||||||
maxIconSize: appGrid.maxIconSize
|
maxIconSize: appGrid.maxIconSize
|
||||||
iconSizeRatio: appGrid.iconSizeRatio
|
iconSizeRatio: appGrid.iconSizeRatio
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -12,7 +10,6 @@ Rectangle {
|
|||||||
required property var gridView
|
required property var gridView
|
||||||
property int cellWidth: 120
|
property int cellWidth: 120
|
||||||
property int cellHeight: 120
|
property int cellHeight: 120
|
||||||
property int cellPadding: 8
|
|
||||||
property int minIconSize: 32
|
property int minIconSize: 32
|
||||||
property int maxIconSize: 64
|
property int maxIconSize: 64
|
||||||
property real iconSizeRatio: 0.5
|
property real iconSizeRatio: 0.5
|
||||||
@@ -31,10 +28,10 @@ Rectangle {
|
|||||||
|
|
||||||
signal itemClicked(int index, var modelData)
|
signal itemClicked(int index, var modelData)
|
||||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||||
signal keyboardNavigationReset()
|
signal keyboardNavigationReset
|
||||||
|
|
||||||
width: cellWidth - cellPadding
|
width: cellWidth
|
||||||
height: cellHeight - cellPadding
|
height: cellHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: currentIndex === index ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : mouseArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : "transparent"
|
color: currentIndex === index ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : mouseArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : "transparent"
|
||||||
|
|
||||||
@@ -87,27 +84,27 @@ Rectangle {
|
|||||||
z: 10
|
z: 10
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
|
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
|
||||||
root.gridView.currentIndex = root.index
|
root.gridView.currentIndex = root.index;
|
||||||
}
|
}
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
root.keyboardNavigationReset()
|
root.keyboardNavigationReset();
|
||||||
}
|
}
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
root.itemClicked(root.index, root.model)
|
root.itemClicked(root.index, root.model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressAndHold: mouse => {
|
onPressAndHold: mouse => {
|
||||||
if (!root.isPlugin) {
|
if (!root.isPlugin) {
|
||||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
const globalPos = mapToItem(null, mouse.x, mouse.y);
|
||||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressed: mouse => {
|
onPressed: mouse => {
|
||||||
if (mouse.button === Qt.RightButton && !root.isPlugin) {
|
if (mouse.button === Qt.RightButton && !root.isPlugin) {
|
||||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
const globalPos = mapToItem(null, mouse.x, mouse.y);
|
||||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
|
||||||
mouse.accepted = true
|
mouse.accepted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user