tabbox/switchers/thumbnail_grid: Load Plasma.Dialog on demand

This avoids keeping old and creating new window thumbnails after the task
switcher is hidden.
wilder/Plasma/6.2
Vlad Zahorodnii 2 years ago
parent a7987f5a33
commit ee24a44cc4
  1. 373
      src/tabbox/switchers/thumbnail_grid/contents/ui/main.qml

@ -20,205 +20,208 @@ KWin.TabBoxSwitcher {
id: tabBox
currentIndex: thumbnailGridView.currentIndex
PlasmaCore.Dialog {
location: PlasmaCore.Types.Floating
visible: tabBox.visible
flags: Qt.X11BypassWindowManagerHint
x: tabBox.screenGeometry.x + tabBox.screenGeometry.width * 0.5 - dialogMainItem.width * 0.5
y: tabBox.screenGeometry.y + tabBox.screenGeometry.height * 0.5 - dialogMainItem.height * 0.5
mainItem: Item {
id: dialogMainItem
focus: true
property int maxWidth: tabBox.screenGeometry.width * 0.9
property int maxHeight: tabBox.screenGeometry.height * 0.7
property real screenFactor: tabBox.screenGeometry.width / tabBox.screenGeometry.height
property int maxGridColumnsByWidth: Math.floor(maxWidth / thumbnailGridView.cellWidth)
property int gridColumns: { // Simple greedy algorithm
// respect screenGeometry
const c = Math.min(thumbnailGridView.count, maxGridColumnsByWidth);
const residue = thumbnailGridView.count % c;
if (residue == 0) {
return c;
}
// start greedy recursion
return columnCountRecursion(c, c, c - residue);
}
property int gridRows: Math.ceil(thumbnailGridView.count / gridColumns)
property int optimalWidth: thumbnailGridView.cellWidth * gridColumns
property int optimalHeight: thumbnailGridView.cellHeight * gridRows
width: Math.min(Math.max(thumbnailGridView.cellWidth, optimalWidth), maxWidth)
height: Math.min(Math.max(thumbnailGridView.cellHeight, optimalHeight), maxHeight)
clip: true
// Step for greedy algorithm
function columnCountRecursion(prevC, prevBestC, prevDiff) {
const c = prevC - 1;
// don't increase vertical extent more than horizontal
// and don't exceed maxHeight
if (prevC * prevC <= thumbnailGridView.count + prevDiff ||
maxHeight < Math.ceil(thumbnailGridView.count / c) * thumbnailGridView.cellHeight) {
return prevBestC;
}
const residue = thumbnailGridView.count % c;
// halts algorithm at some point
if (residue == 0) {
return c;
Instantiator {
active: tabBox.visible
delegate: PlasmaCore.Dialog {
location: PlasmaCore.Types.Floating
visible: true
flags: Qt.X11BypassWindowManagerHint
x: tabBox.screenGeometry.x + tabBox.screenGeometry.width * 0.5 - dialogMainItem.width * 0.5
y: tabBox.screenGeometry.y + tabBox.screenGeometry.height * 0.5 - dialogMainItem.height * 0.5
mainItem: Item {
id: dialogMainItem
focus: true
property int maxWidth: tabBox.screenGeometry.width * 0.9
property int maxHeight: tabBox.screenGeometry.height * 0.7
property real screenFactor: tabBox.screenGeometry.width / tabBox.screenGeometry.height
property int maxGridColumnsByWidth: Math.floor(maxWidth / thumbnailGridView.cellWidth)
property int gridColumns: { // Simple greedy algorithm
// respect screenGeometry
const c = Math.min(thumbnailGridView.count, maxGridColumnsByWidth);
const residue = thumbnailGridView.count % c;
if (residue == 0) {
return c;
}
// start greedy recursion
return columnCountRecursion(c, c, c - residue);
}
// empty slots
const diff = c - residue;
// compare it to previous count of empty slots
if (diff < prevDiff) {
return columnCountRecursion(c, c, diff);
} else if (diff == prevDiff) {
// when it's the same try again, we'll stop early enough thanks to the landscape mode condition
property int gridRows: Math.ceil(thumbnailGridView.count / gridColumns)
property int optimalWidth: thumbnailGridView.cellWidth * gridColumns
property int optimalHeight: thumbnailGridView.cellHeight * gridRows
width: Math.min(Math.max(thumbnailGridView.cellWidth, optimalWidth), maxWidth)
height: Math.min(Math.max(thumbnailGridView.cellHeight, optimalHeight), maxHeight)
clip: true
// Step for greedy algorithm
function columnCountRecursion(prevC, prevBestC, prevDiff) {
const c = prevC - 1;
// don't increase vertical extent more than horizontal
// and don't exceed maxHeight
if (prevC * prevC <= thumbnailGridView.count + prevDiff ||
maxHeight < Math.ceil(thumbnailGridView.count / c) * thumbnailGridView.cellHeight) {
return prevBestC;
}
const residue = thumbnailGridView.count % c;
// halts algorithm at some point
if (residue == 0) {
return c;
}
// empty slots
const diff = c - residue;
// compare it to previous count of empty slots
if (diff < prevDiff) {
return columnCountRecursion(c, c, diff);
} else if (diff == prevDiff) {
// when it's the same try again, we'll stop early enough thanks to the landscape mode condition
return columnCountRecursion(c, prevBestC, diff);
}
// when we've found a local minimum choose this one (greedy)
return columnCountRecursion(c, prevBestC, diff);
}
// when we've found a local minimum choose this one (greedy)
return columnCountRecursion(c, prevBestC, diff);
}
// Just to get the margin sizes
KSvg.FrameSvgItem {
id: hoverItem
imagePath: "widgets/viewitem"
prefix: "hover"
visible: false
}
GridView {
id: thumbnailGridView
anchors.fill: parent
focus: true
model: tabBox.model
readonly property int iconSize: Kirigami.Units.iconSizes.huge
readonly property int captionRowHeight: Kirigami.Units.gridUnit * 2
readonly property int columnSpacing: Kirigami.Units.gridUnit
readonly property int thumbnailWidth: Kirigami.Units.gridUnit * 16
readonly property int thumbnailHeight: thumbnailWidth * (1.0/dialogMainItem.screenFactor)
cellWidth: hoverItem.margins.left + thumbnailWidth + hoverItem.margins.right
cellHeight: hoverItem.margins.top + captionRowHeight + thumbnailHeight + hoverItem.margins.bottom
keyNavigationWraps: true
highlightMoveDuration: 0
delegate: MouseArea {
id: thumbnailGridItem
width: thumbnailGridView.cellWidth
height: thumbnailGridView.cellHeight
focus: GridView.isCurrentItem
hoverEnabled: true
Accessible.name: model.caption
Accessible.role: Accessible.ListItem
onClicked: {
thumbnailGridView.currentIndex = index;
}
ColumnLayout {
id: columnLayout
z: 0
spacing: thumbnailGridView.columnSpacing
anchors.fill: parent
anchors.leftMargin: hoverItem.margins.left * 2
anchors.topMargin: hoverItem.margins.top * 2
anchors.rightMargin: hoverItem.margins.right * 2
anchors.bottomMargin: hoverItem.margins.bottom * 2
// KWin.WindowThumbnail needs a container
// otherwise it will be drawn the same size as the parent ColumnLayout
Item {
Layout.fillWidth: true
Layout.fillHeight: true
KWin.WindowThumbnail {
anchors.fill: parent
wId: windowId
}
// Just to get the margin sizes
KSvg.FrameSvgItem {
id: hoverItem
imagePath: "widgets/viewitem"
prefix: "hover"
visible: false
}
Kirigami.Icon {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.bottom
anchors.verticalCenterOffset: Math.round(-thumbnailGridView.iconSize / 4)
width: thumbnailGridView.iconSize
height: thumbnailGridView.iconSize
GridView {
id: thumbnailGridView
anchors.fill: parent
focus: true
model: tabBox.model
readonly property int iconSize: Kirigami.Units.iconSizes.huge
readonly property int captionRowHeight: Kirigami.Units.gridUnit * 2
readonly property int columnSpacing: Kirigami.Units.gridUnit
readonly property int thumbnailWidth: Kirigami.Units.gridUnit * 16
readonly property int thumbnailHeight: thumbnailWidth * (1.0/dialogMainItem.screenFactor)
cellWidth: hoverItem.margins.left + thumbnailWidth + hoverItem.margins.right
cellHeight: hoverItem.margins.top + captionRowHeight + thumbnailHeight + hoverItem.margins.bottom
keyNavigationWraps: true
highlightMoveDuration: 0
delegate: MouseArea {
id: thumbnailGridItem
width: thumbnailGridView.cellWidth
height: thumbnailGridView.cellHeight
focus: GridView.isCurrentItem
hoverEnabled: true
Accessible.name: model.caption
Accessible.role: Accessible.ListItem
onClicked: {
thumbnailGridView.currentIndex = index;
}
source: model.icon
}
ColumnLayout {
id: columnLayout
z: 0
spacing: thumbnailGridView.columnSpacing
anchors.fill: parent
anchors.leftMargin: hoverItem.margins.left * 2
anchors.topMargin: hoverItem.margins.top * 2
anchors.rightMargin: hoverItem.margins.right * 2
anchors.bottomMargin: hoverItem.margins.bottom * 2
// KWin.WindowThumbnail needs a container
// otherwise it will be drawn the same size as the parent ColumnLayout
Item {
Layout.fillWidth: true
Layout.fillHeight: true
KWin.WindowThumbnail {
anchors.fill: parent
wId: windowId
}
Kirigami.Icon {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.bottom
anchors.verticalCenterOffset: Math.round(-thumbnailGridView.iconSize / 4)
width: thumbnailGridView.iconSize
height: thumbnailGridView.iconSize
PlasmaComponents3.ToolButton {
id: closeButton
anchors {
right: parent.right
top: parent.top
// Deliberately touch the inner edges of the frame
rightMargin: -columnLayout.anchors.rightMargin
topMargin: -columnLayout.anchors.topMargin
source: model.icon
}
visible: model.closeable && typeof tabBox.model.close !== 'undefined' &&
(thumbnailGridItem.containsMouse
|| closeButton.hovered
|| thumbnailGridItem.focus
|| Kirigami.Settings.tabletMode
|| Kirigami.Settings.hasTransientTouchInput
)
icon.name: 'window-close-symbolic'
onClicked: {
tabBox.model.close(index);
PlasmaComponents3.ToolButton {
id: closeButton
anchors {
right: parent.right
top: parent.top
// Deliberately touch the inner edges of the frame
rightMargin: -columnLayout.anchors.rightMargin
topMargin: -columnLayout.anchors.topMargin
}
visible: model.closeable && typeof tabBox.model.close !== 'undefined' &&
(thumbnailGridItem.containsMouse
|| closeButton.hovered
|| thumbnailGridItem.focus
|| Kirigami.Settings.tabletMode
|| Kirigami.Settings.hasTransientTouchInput
)
icon.name: 'window-close-symbolic'
onClicked: {
tabBox.model.close(index);
}
}
}
}
PlasmaComponents3.Label {
Layout.fillWidth: true
text: model.caption
font.weight: thumbnailGridItem.focus ? Font.Bold : Font.Normal
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
textFormat: Text.PlainText
elide: Text.ElideRight
PlasmaComponents3.Label {
Layout.fillWidth: true
text: model.caption
font.weight: thumbnailGridItem.focus ? Font.Bold : Font.Normal
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
textFormat: Text.PlainText
elide: Text.ElideRight
}
}
}
} // GridView.delegate
} // GridView.delegate
highlight: KSvg.FrameSvgItem {
imagePath: "widgets/viewitem"
prefix: "hover"
}
highlight: KSvg.FrameSvgItem {
imagePath: "widgets/viewitem"
prefix: "hover"
}
Connections {
target: tabBox
function onCurrentIndexChanged() {
thumbnailGridView.currentIndex = tabBox.currentIndex;
Connections {
target: tabBox
function onCurrentIndexChanged() {
thumbnailGridView.currentIndex = tabBox.currentIndex;
}
}
} // GridView
Keys.onPressed: {
if (event.key == Qt.Key_Left) {
thumbnailGridView.moveCurrentIndexLeft();
} else if (event.key == Qt.Key_Right) {
thumbnailGridView.moveCurrentIndexRight();
} else if (event.key == Qt.Key_Up) {
thumbnailGridView.moveCurrentIndexUp();
} else if (event.key == Qt.Key_Down) {
thumbnailGridView.moveCurrentIndexDown();
} else {
return;
}
}
} // GridView
Keys.onPressed: {
if (event.key == Qt.Key_Left) {
thumbnailGridView.moveCurrentIndexLeft();
} else if (event.key == Qt.Key_Right) {
thumbnailGridView.moveCurrentIndexRight();
} else if (event.key == Qt.Key_Up) {
thumbnailGridView.moveCurrentIndexUp();
} else if (event.key == Qt.Key_Down) {
thumbnailGridView.moveCurrentIndexDown();
} else {
return;
}
thumbnailGridView.currentIndexChanged(thumbnailGridView.currentIndex);
}
} // Dialog.mainItem
} // Dialog
thumbnailGridView.currentIndexChanged(thumbnailGridView.currentIndex);
}
} // Dialog.mainItem
} // Dialog
} // Instantiator
}

Loading…
Cancel
Save