mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 07:52:50 -05:00
Consolidate launcher (#615)
* refactor: Consolidate Icon Renderer for launcher Launcher icons are built on 2 places Spotlight and AppDrawer This duplicates the maintanance effort, every time something changes on one place must be replicated on the other. This commit consolidates the Icon renderer in a shared component. * refactor: Consolidate Launcher list and grid List and GRid builders were split in 2 components. this commit adds separate delegates to be reused as shared components.
This commit is contained in:
committed by
GitHub
parent
ed0b80008f
commit
3abee7f2f5
@@ -73,125 +73,22 @@ Rectangle {
|
|||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: AppLauncherListDelegate {
|
||||||
width: ListView.view.width
|
listView: resultsList
|
||||||
height: resultsList.itemHeight
|
itemHeight: resultsList.itemHeight
|
||||||
radius: Theme.cornerRadius
|
iconSize: resultsList.iconSize
|
||||||
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
showDescription: resultsList.showDescription
|
||||||
|
hoverUpdatesSelection: resultsList.hoverUpdatesSelection
|
||||||
Row {
|
keyboardNavigationActive: resultsList.keyboardNavigationActive
|
||||||
anchors.fill: parent
|
isCurrentItem: ListView.isCurrentItem
|
||||||
anchors.margins: Theme.spacingM
|
iconMaterialSizeAdjustment: 0
|
||||||
spacing: Theme.spacingL
|
iconUnicodeScale: 0.8
|
||||||
|
onItemClicked: (idx, modelData) => resultsList.itemClicked(idx, modelData)
|
||||||
Item {
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
width: resultsList.iconSize
|
const modalPos = resultsContainer.parent.mapFromItem(null, mouseX, mouseY)
|
||||||
height: resultsList.iconSize
|
resultsList.itemRightClicked(idx, modelData, modalPos.x, modalPos.y)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: model.icon !== undefined && model.icon !== ""
|
|
||||||
|
|
||||||
property string iconValue: model.icon || ""
|
|
||||||
property bool isMaterial: iconValue.indexOf("material:") === 0
|
|
||||||
property bool isUnicode: iconValue.indexOf("unicode:") === 0
|
|
||||||
property string materialName: isMaterial ? iconValue.substring(9) : ""
|
|
||||||
property string unicodeChar: isUnicode ? iconValue.substring(8) : ""
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: parent.materialName
|
|
||||||
size: resultsList.iconSize
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isMaterial
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: parent.unicodeChar
|
|
||||||
font.pixelSize: resultsList.iconSize * 0.8
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isUnicode
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: listIconImg
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
source: parent.isMaterial || parent.isUnicode ? "" : Quickshell.iconPath(parent.iconValue, true)
|
|
||||||
asynchronous: true
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && status === Image.Ready
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && !listIconImg.visible
|
|
||||||
color: Theme.surfaceLight
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.width: 1
|
|
||||||
border.color: Theme.primarySelected
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
|
||||||
font.pixelSize: resultsList.iconSize * 0.4
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: (model.icon !== undefined && model.icon !== "") ? (parent.width - resultsList.iconSize - Theme.spacingL) : parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: model.name || ""
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
maximumLineCount: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: model.comment || "Application"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
visible: resultsList.showDescription && model.comment && model.comment.length > 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: listMouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
z: 10
|
|
||||||
onEntered: () => {
|
|
||||||
if (resultsList.hoverUpdatesSelection && !resultsList.keyboardNavigationActive)
|
|
||||||
resultsList.currentIndex = index
|
|
||||||
}
|
|
||||||
onPositionChanged: () => {
|
|
||||||
resultsList.keyboardNavigationReset()
|
|
||||||
}
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
resultsList.itemClicked(index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton && !model.isPlugin) {
|
|
||||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
|
||||||
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
|
||||||
resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onKeyboardNavigationReset: resultsList.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,113 +157,23 @@ Rectangle {
|
|||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: AppLauncherGridDelegate {
|
||||||
width: resultsGrid.cellWidth - resultsGrid.cellPadding
|
gridView: resultsGrid
|
||||||
height: resultsGrid.cellHeight - resultsGrid.cellPadding
|
cellWidth: resultsGrid.cellWidth
|
||||||
radius: Theme.cornerRadius
|
cellHeight: resultsGrid.cellHeight
|
||||||
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
cellPadding: resultsGrid.cellPadding
|
||||||
|
minIconSize: resultsGrid.minIconSize
|
||||||
Column {
|
maxIconSize: resultsGrid.maxIconSize
|
||||||
anchors.centerIn: parent
|
iconSizeRatio: resultsGrid.iconSizeRatio
|
||||||
spacing: Theme.spacingS
|
hoverUpdatesSelection: resultsGrid.hoverUpdatesSelection
|
||||||
|
keyboardNavigationActive: resultsGrid.keyboardNavigationActive
|
||||||
Item {
|
currentIndex: resultsGrid.currentIndex
|
||||||
property int iconSize: Math.min(resultsGrid.maxIconSize, Math.max(resultsGrid.minIconSize, resultsGrid.cellWidth * resultsGrid.iconSizeRatio))
|
onItemClicked: (idx, modelData) => resultsGrid.itemClicked(idx, modelData)
|
||||||
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
width: iconSize
|
const modalPos = resultsContainer.parent.mapFromItem(null, mouseX, mouseY)
|
||||||
height: iconSize
|
resultsGrid.itemRightClicked(idx, modelData, modalPos.x, modalPos.y)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: model.icon !== undefined && model.icon !== ""
|
|
||||||
|
|
||||||
property string iconValue: model.icon || ""
|
|
||||||
property bool isMaterial: iconValue.indexOf("material:") === 0
|
|
||||||
property bool isUnicode: iconValue.indexOf("unicode:") === 0
|
|
||||||
property string materialName: isMaterial ? iconValue.substring(9) : ""
|
|
||||||
property string unicodeChar: isUnicode ? iconValue.substring(8) : ""
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: parent.materialName
|
|
||||||
size: parent.iconSize
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isMaterial
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: parent.unicodeChar
|
|
||||||
font.pixelSize: parent.iconSize * 0.8
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isUnicode
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: gridIconImg
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
source: parent.isMaterial || parent.isUnicode ? "" : Quickshell.iconPath(parent.iconValue, true)
|
|
||||||
smooth: true
|
|
||||||
asynchronous: true
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && status === Image.Ready
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && !gridIconImg.visible
|
|
||||||
color: Theme.surfaceLight
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.width: 1
|
|
||||||
border.color: Theme.primarySelected
|
|
||||||
|
|
||||||
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)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
width: resultsGrid.cellWidth - 12
|
|
||||||
text: model.name || ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
maximumLineCount: 1
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: gridMouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
z: 10
|
|
||||||
onEntered: () => {
|
|
||||||
if (resultsGrid.hoverUpdatesSelection && !resultsGrid.keyboardNavigationActive)
|
|
||||||
resultsGrid.currentIndex = index
|
|
||||||
}
|
|
||||||
onPositionChanged: () => {
|
|
||||||
resultsGrid.keyboardNavigationReset()
|
|
||||||
}
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
resultsGrid.itemClicked(index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton && !model.isPlugin) {
|
|
||||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
|
||||||
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
|
||||||
resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onKeyboardNavigationReset: resultsGrid.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -389,134 +389,27 @@ DankPopout {
|
|||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: AppLauncherListDelegate {
|
||||||
width: ListView.view.width
|
listView: appList
|
||||||
height: appList.itemHeight
|
itemHeight: appList.itemHeight
|
||||||
radius: Theme.cornerRadius
|
iconSize: appList.iconSize
|
||||||
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
showDescription: appList.showDescription
|
||||||
|
hoverUpdatesSelection: appList.hoverUpdatesSelection
|
||||||
Row {
|
keyboardNavigationActive: appList.keyboardNavigationActive
|
||||||
anchors.fill: parent
|
isCurrentItem: ListView.isCurrentItem
|
||||||
anchors.margins: Theme.spacingM
|
mouseAreaLeftMargin: Theme.spacingS
|
||||||
spacing: Theme.spacingL
|
mouseAreaRightMargin: Theme.spacingS
|
||||||
|
mouseAreaBottomMargin: Theme.spacingM
|
||||||
Item {
|
iconMargins: Theme.spacingXS
|
||||||
width: appList.iconSize
|
iconFallbackLeftMargin: Theme.spacingS
|
||||||
height: appList.iconSize
|
iconFallbackRightMargin: Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
iconFallbackBottomMargin: Theme.spacingM
|
||||||
visible: model.icon !== undefined && model.icon !== ""
|
onItemClicked: (idx, modelData) => appList.itemClicked(idx, modelData)
|
||||||
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
property string iconValue: model.icon || ""
|
const panelPos = contextMenu.parent.mapFromItem(null, mouseX, mouseY)
|
||||||
property bool isMaterial: iconValue.indexOf("material:") === 0
|
appList.itemRightClicked(idx, modelData, panelPos.x, panelPos.y)
|
||||||
property bool isUnicode: iconValue.indexOf("unicode:") === 0
|
|
||||||
property string materialName: isMaterial ? iconValue.substring(9) : ""
|
|
||||||
property string unicodeChar: isUnicode ? iconValue.substring(8) : ""
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: parent.materialName
|
|
||||||
size: appList.iconSize - Theme.spacingM
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isMaterial
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: parent.unicodeChar
|
|
||||||
font.pixelSize: appList.iconSize * 0.7
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isUnicode
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: listIconImg
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Theme.spacingXS
|
|
||||||
source: parent.isMaterial || parent.isUnicode ? "" : Quickshell.iconPath(parent.iconValue, true)
|
|
||||||
smooth: true
|
|
||||||
asynchronous: true
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && status === Image.Ready
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingM
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && listIconImg.status !== Image.Ready
|
|
||||||
color: Theme.surfaceLight
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.width: 0
|
|
||||||
border.color: Theme.primarySelected
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: (model.icon !== undefined && model.icon !== "") ? (parent.width - appList.iconSize - Theme.spacingL) : parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: model.name || ""
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
maximumLineCount: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: model.comment || "Application"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
visible: appList.showDescription && model.comment && model.comment.length > 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: listMouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingM
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
z: 10
|
|
||||||
onEntered: {
|
|
||||||
if (appList.hoverUpdatesSelection && !appList.keyboardNavigationActive)
|
|
||||||
appList.currentIndex = index
|
|
||||||
}
|
|
||||||
onPositionChanged: {
|
|
||||||
appList.keyboardNavigationReset()
|
|
||||||
}
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
appList.itemClicked(index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
|
||||||
var globalPos = mapToItem(null, mouse.x, mouse.y)
|
|
||||||
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
|
||||||
appList.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onKeyboardNavigationReset: appList.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,122 +480,30 @@ DankPopout {
|
|||||||
appLauncher.keyboardNavigationActive = false
|
appLauncher.keyboardNavigationActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: AppLauncherGridDelegate {
|
||||||
width: appGrid.cellWidth - appGrid.cellPadding
|
gridView: appGrid
|
||||||
height: appGrid.cellHeight - appGrid.cellPadding
|
cellWidth: appGrid.cellWidth
|
||||||
radius: Theme.cornerRadius
|
cellHeight: appGrid.cellHeight
|
||||||
color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
cellPadding: appGrid.cellPadding
|
||||||
|
minIconSize: appGrid.minIconSize
|
||||||
Column {
|
maxIconSize: appGrid.maxIconSize
|
||||||
anchors.centerIn: parent
|
iconSizeRatio: appGrid.iconSizeRatio
|
||||||
spacing: Theme.spacingS
|
hoverUpdatesSelection: appGrid.hoverUpdatesSelection
|
||||||
|
keyboardNavigationActive: appGrid.keyboardNavigationActive
|
||||||
Item {
|
currentIndex: appGrid.currentIndex
|
||||||
property int iconSize: Math.min(appGrid.maxIconSize, Math.max(appGrid.minIconSize, appGrid.cellWidth * appGrid.iconSizeRatio))
|
mouseAreaLeftMargin: Theme.spacingS
|
||||||
|
mouseAreaRightMargin: Theme.spacingS
|
||||||
width: iconSize
|
mouseAreaBottomMargin: Theme.spacingS
|
||||||
height: iconSize
|
iconFallbackLeftMargin: Theme.spacingS
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
iconFallbackRightMargin: Theme.spacingS
|
||||||
visible: model.icon !== undefined && model.icon !== ""
|
iconFallbackBottomMargin: Theme.spacingS
|
||||||
|
iconMaterialSizeAdjustment: Theme.spacingL
|
||||||
property string iconValue: model.icon || ""
|
onItemClicked: (idx, modelData) => appGrid.itemClicked(idx, modelData)
|
||||||
property bool isMaterial: iconValue.indexOf("material:") === 0
|
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||||
property bool isUnicode: iconValue.indexOf("unicode:") === 0
|
const panelPos = contextMenu.parent.mapFromItem(null, mouseX, mouseY)
|
||||||
property string materialName: isMaterial ? iconValue.substring(9) : ""
|
appGrid.itemRightClicked(idx, modelData, panelPos.x, panelPos.y)
|
||||||
property string unicodeChar: isUnicode ? iconValue.substring(8) : ""
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: parent.materialName
|
|
||||||
size: parent.iconSize - Theme.spacingL
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isMaterial
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: parent.unicodeChar
|
|
||||||
font.pixelSize: parent.iconSize * 0.8
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: parent.isUnicode
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: gridIconImg
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
source: parent.isMaterial || parent.isUnicode ? "" : Quickshell.iconPath(parent.iconValue, true)
|
|
||||||
smooth: true
|
|
||||||
asynchronous: true
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && status === Image.Ready
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
visible: !parent.isMaterial && !parent.isUnicode && gridIconImg.status !== Image.Ready
|
|
||||||
color: Theme.surfaceLight
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.width: 0
|
|
||||||
border.color: Theme.primarySelected
|
|
||||||
|
|
||||||
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)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
width: appGrid.cellWidth - 12
|
|
||||||
text: model.name || ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
maximumLineCount: 1
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: gridMouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
z: 10
|
|
||||||
onEntered: {
|
|
||||||
if (appGrid.hoverUpdatesSelection && !appGrid.keyboardNavigationActive)
|
|
||||||
appGrid.currentIndex = index
|
|
||||||
}
|
|
||||||
onPositionChanged: {
|
|
||||||
appGrid.keyboardNavigationReset()
|
|
||||||
}
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
appGrid.itemClicked(index, model)
|
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
|
||||||
var globalPos = mapToItem(null, mouse.x, mouse.y)
|
|
||||||
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
|
||||||
appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onKeyboardNavigationReset: appGrid.keyboardNavigationReset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
80
Widgets/AppIconRenderer.qml
Normal file
80
Widgets/AppIconRenderer.qml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property string iconValue
|
||||||
|
required property int iconSize
|
||||||
|
property string fallbackText: "A"
|
||||||
|
property color iconColor: Theme.surfaceText
|
||||||
|
property color fallbackBackgroundColor: Theme.surfaceLight
|
||||||
|
property color fallbackTextColor: Theme.primary
|
||||||
|
property real materialIconSizeAdjustment: Theme.spacingM
|
||||||
|
property real unicodeIconScale: 0.7
|
||||||
|
property real fallbackTextScale: 0.4
|
||||||
|
property alias iconMargins: iconImg.anchors.margins
|
||||||
|
property real fallbackLeftMargin: 0
|
||||||
|
property real fallbackRightMargin: 0
|
||||||
|
property real fallbackTopMargin: 0
|
||||||
|
property real fallbackBottomMargin: 0
|
||||||
|
|
||||||
|
property bool isMaterial: iconValue.indexOf("material:") === 0
|
||||||
|
property bool isUnicode: iconValue.indexOf("unicode:") === 0
|
||||||
|
property string materialName: isMaterial ? iconValue.substring(9) : ""
|
||||||
|
property string unicodeChar: isUnicode ? iconValue.substring(8) : ""
|
||||||
|
|
||||||
|
visible: iconValue !== undefined && iconValue !== ""
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: root.materialName
|
||||||
|
size: root.iconSize - root.materialIconSizeAdjustment
|
||||||
|
color: root.iconColor
|
||||||
|
visible: root.isMaterial
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: root.unicodeChar
|
||||||
|
font.pixelSize: root.iconSize * root.unicodeIconScale
|
||||||
|
color: root.iconColor
|
||||||
|
visible: root.isUnicode
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
id: iconImg
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
source: root.isMaterial || root.isUnicode ? "" : Quickshell.iconPath(root.iconValue, true)
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
visible: !root.isMaterial && !root.isUnicode && status === Image.Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: fallbackRect
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: root.fallbackLeftMargin
|
||||||
|
anchors.rightMargin: root.fallbackRightMargin
|
||||||
|
anchors.topMargin: root.fallbackTopMargin
|
||||||
|
anchors.bottomMargin: root.fallbackBottomMargin
|
||||||
|
visible: !root.isMaterial && !root.isUnicode && iconImg.status !== Image.Ready
|
||||||
|
color: root.fallbackBackgroundColor
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.width: 0
|
||||||
|
border.color: Theme.primarySelected
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: root.fallbackText
|
||||||
|
font.pixelSize: root.iconSize * root.fallbackTextScale
|
||||||
|
color: root.fallbackTextColor
|
||||||
|
font.weight: Font.Bold
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
Widgets/AppLauncherGridDelegate.qml
Normal file
104
Widgets/AppLauncherGridDelegate.qml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var model
|
||||||
|
required property int index
|
||||||
|
required property var gridView
|
||||||
|
property int cellWidth: 120
|
||||||
|
property int cellHeight: 120
|
||||||
|
property int cellPadding: 8
|
||||||
|
property int minIconSize: 32
|
||||||
|
property int maxIconSize: 64
|
||||||
|
property real iconSizeRatio: 0.5
|
||||||
|
property bool hoverUpdatesSelection: true
|
||||||
|
property bool keyboardNavigationActive: false
|
||||||
|
property int currentIndex: -1
|
||||||
|
property bool isPlugin: model?.isPlugin || false
|
||||||
|
property real mouseAreaLeftMargin: 0
|
||||||
|
property real mouseAreaRightMargin: 0
|
||||||
|
property real mouseAreaBottomMargin: 0
|
||||||
|
property real iconFallbackLeftMargin: 0
|
||||||
|
property real iconFallbackRightMargin: 0
|
||||||
|
property real iconFallbackBottomMargin: 0
|
||||||
|
property real iconMaterialSizeAdjustment: 0
|
||||||
|
property real iconUnicodeScale: 0.8
|
||||||
|
|
||||||
|
signal itemClicked(int index, var modelData)
|
||||||
|
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||||
|
signal keyboardNavigationReset()
|
||||||
|
|
||||||
|
width: cellWidth - cellPadding
|
||||||
|
height: cellHeight - cellPadding
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: currentIndex === index ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
AppIconRenderer {
|
||||||
|
property int computedIconSize: Math.min(root.maxIconSize, Math.max(root.minIconSize, root.cellWidth * root.iconSizeRatio))
|
||||||
|
|
||||||
|
width: computedIconSize
|
||||||
|
height: computedIconSize
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
iconValue: model.icon || ""
|
||||||
|
iconSize: computedIconSize
|
||||||
|
fallbackText: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||||
|
materialIconSizeAdjustment: root.iconMaterialSizeAdjustment
|
||||||
|
unicodeIconScale: root.iconUnicodeScale
|
||||||
|
fallbackTextScale: Math.min(28, computedIconSize * 0.5) / computedIconSize
|
||||||
|
iconMargins: 0
|
||||||
|
fallbackLeftMargin: root.iconFallbackLeftMargin
|
||||||
|
fallbackRightMargin: root.iconFallbackRightMargin
|
||||||
|
fallbackBottomMargin: root.iconFallbackBottomMargin
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: root.cellWidth - 12
|
||||||
|
text: model.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
maximumLineCount: 1
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: root.mouseAreaLeftMargin
|
||||||
|
anchors.rightMargin: root.mouseAreaRightMargin
|
||||||
|
anchors.bottomMargin: root.mouseAreaBottomMargin
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
z: 10
|
||||||
|
onEntered: {
|
||||||
|
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
|
||||||
|
root.gridView.currentIndex = root.index
|
||||||
|
}
|
||||||
|
onPositionChanged: {
|
||||||
|
root.keyboardNavigationReset()
|
||||||
|
}
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
root.itemClicked(root.index, root.model)
|
||||||
|
} else if (mouse.button === Qt.RightButton && !root.isPlugin) {
|
||||||
|
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
Widgets/AppLauncherListDelegate.qml
Normal file
114
Widgets/AppLauncherListDelegate.qml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var model
|
||||||
|
required property int index
|
||||||
|
required property var listView
|
||||||
|
property int itemHeight: 60
|
||||||
|
property int iconSize: 40
|
||||||
|
property bool showDescription: true
|
||||||
|
property bool hoverUpdatesSelection: true
|
||||||
|
property bool keyboardNavigationActive: false
|
||||||
|
property bool isCurrentItem: false
|
||||||
|
property bool isPlugin: model?.isPlugin || false
|
||||||
|
property real mouseAreaLeftMargin: 0
|
||||||
|
property real mouseAreaRightMargin: 0
|
||||||
|
property real mouseAreaBottomMargin: 0
|
||||||
|
property real iconMargins: 0
|
||||||
|
property real iconFallbackLeftMargin: 0
|
||||||
|
property real iconFallbackRightMargin: 0
|
||||||
|
property real iconFallbackBottomMargin: 0
|
||||||
|
property real iconMaterialSizeAdjustment: Theme.spacingM
|
||||||
|
property real iconUnicodeScale: 0.7
|
||||||
|
|
||||||
|
signal itemClicked(int index, var modelData)
|
||||||
|
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||||
|
signal keyboardNavigationReset()
|
||||||
|
|
||||||
|
width: listView.width
|
||||||
|
height: itemHeight
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: isCurrentItem ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
|
AppIconRenderer {
|
||||||
|
width: root.iconSize
|
||||||
|
height: root.iconSize
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconValue: model.icon || ""
|
||||||
|
iconSize: root.iconSize
|
||||||
|
fallbackText: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||||
|
iconMargins: root.iconMargins
|
||||||
|
fallbackLeftMargin: root.iconFallbackLeftMargin
|
||||||
|
fallbackRightMargin: root.iconFallbackRightMargin
|
||||||
|
fallbackBottomMargin: root.iconFallbackBottomMargin
|
||||||
|
materialIconSizeAdjustment: root.iconMaterialSizeAdjustment
|
||||||
|
unicodeIconScale: root.iconUnicodeScale
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: (model.icon !== undefined && model.icon !== "") ? (parent.width - root.iconSize - Theme.spacingL) : parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: model.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: model.comment || "Application"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
visible: root.showDescription && model.comment && model.comment.length > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: root.mouseAreaLeftMargin
|
||||||
|
anchors.rightMargin: root.mouseAreaRightMargin
|
||||||
|
anchors.bottomMargin: root.mouseAreaBottomMargin
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
z: 10
|
||||||
|
onEntered: {
|
||||||
|
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
|
||||||
|
root.listView.currentIndex = root.index
|
||||||
|
}
|
||||||
|
onPositionChanged: {
|
||||||
|
root.keyboardNavigationReset()
|
||||||
|
}
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
root.itemClicked(root.index, root.model)
|
||||||
|
} else if (mouse.button === Qt.RightButton && !root.isPlugin) {
|
||||||
|
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user