You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
9.2 KiB
QML

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons 2.0
import org.kde.kwin 2.0 as KWin
import FishUI 1.0 as FishUI
// https://techbase.kde.org/Development/Tutorials/KWin/WindowSwitcher
KWin.Switcher {
id: tabBox
currentIndex: thumbnailGridView.currentIndex
Window {
id: dialog
visible: tabBox.visible
flags: Qt.BypassWindowManagerHint | Qt.FramelessWindowHint
color: "transparent"
property int maxWidth: tabBox.screenGeometry.width * 0.95
property int maxHeight: tabBox.screenGeometry.height * 0.7
property int optimalWidth: thumbnailGridView.cellWidth * gridColumns
property int optimalHeight: thumbnailGridView.cellHeight * gridRows
property int maxGridColumnsByWidth: Math.floor(maxWidth / thumbnailGridView.cellWidth)
property int gridColumns: maxGridColumnsByWidth
property int gridRows: Math.ceil(thumbnailGridView.count / gridColumns)
width: Math.min(Math.max(thumbnailGridView.cellWidth, optimalWidth), maxWidth)
height: Math.min(Math.max(thumbnailGridView.cellHeight, optimalHeight), maxHeight)
x: tabBox.screenGeometry.x + (tabBox.screenGeometry.width - dialog.width) / 2
y: tabBox.screenGeometry.y + (tabBox.screenGeometry.height - dialog.height) / 2
FishUI.WindowHelper {
id: windowHelper
}
FishUI.WindowBlur {
view: dialog
geometry: Qt.rect(dialog.x, dialog.y, dialog.width, dialog.height)
windowRadius: _background.radius
enabled: windowHelper.compositing
}
FishUI.WindowShadow {
view: dialog
geometry: Qt.rect(dialog.x, dialog.y, dialog.width, dialog.height)
radius: _background.radius
}
Rectangle {
id: _background
anchors.fill: parent
radius: windowHelper.compositing ? 14 : 0
color: FishUI.Theme.backgroundColor
opacity: windowHelper.compositing ? FishUI.Theme.darkMode ? 0.3 : 0.4 : 1.0
border.color: FishUI.Theme.darkMode ? "#686868" : "#D9D9D9"
border.width: windowHelper.compositing ? 0 : 1
}
onVisibleChanged: {
if (visible) {
dialogMainItem.calculateColumnCount();
} else {
thumbnailGridView.highCount = 0;
}
}
Item {
id: dialogMainItem
anchors.fill: parent
property real screenFactor: tabBox.screenGeometry.width / tabBox.screenGeometry.height
property bool canStretchX: false
property bool canStretchY: false
clip: true
// simple greedy algorithm
function calculateColumnCount() {
// respect screenGeometry
var c = Math.min(thumbnailGridView.count, dialog.maxGridColumnsByWidth);
var residue = thumbnailGridView.count % c;
if (residue == 0) {
dialog.gridColumns = c;
return;
}
// start greedy recursion
dialog.gridColumns = columnCountRecursion(c, c, c - residue);
}
// step for greedy algorithm
function columnCountRecursion(prevC, prevBestC, prevDiff) {
var c = prevC - 1;
// don't increase vertical extent more than horizontal
// and don't exceed maxHeight
if (prevC * prevC <= thumbnailGridView.count + prevDiff ||
dialog.maxHeight < Math.ceil(thumbnailGridView.count / c) * thumbnailGridView.cellHeight) {
return prevBestC;
}
var residue = thumbnailGridView.count % c;
// halts algorithm at some point
if (residue == 0) {
return c;
}
// empty slots
var 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);
}
property bool mouseEnabled: false
MouseArea {
id: mouseDetector
anchors.fill: parent
hoverEnabled: true
onPositionChanged: dialogMainItem.mouseEnabled = true
}
GridView {
id: thumbnailGridView
model: tabBox.model
// interactive: false // Disable drag to scroll
anchors.fill: parent
property int captionRowHeight: 22
property int thumbnailWidth: 300
property int thumbnailHeight: thumbnailWidth * (1.0 / dialogMainItem.screenFactor)
cellWidth: thumbnailWidth
cellHeight: captionRowHeight + thumbnailHeight
height: cellHeight
clip: true
// allow expansion on increasing count
property int highCount: 0
onCountChanged: {
if (highCount != count) {
dialogMainItem.calculateColumnCount();
highCount = count;
}
}
delegate: Item {
property bool isCurrent: thumbnailGridView.currentIndex === index
width: thumbnailGridView.cellWidth
height: thumbnailGridView.cellHeight
MouseArea {
anchors.fill: parent
// hoverEnabled: dialogMainItem.mouseEnabled
// onEntered: parent.hover()
onClicked: {
parent.select()
// dialog.close() // Doesn't end the effects until you release Alt.
}
}
function select() {
thumbnailGridView.currentIndex = index;
thumbnailGridView.currentIndexChanged(thumbnailGridView.currentIndex);
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
QIconItem {
id: iconItem
// source: model.icon
icon: model.icon
width: parent.height * 0.5
height: parent.height * 0.5
state: index == thumbnailGridView.currentIndex ? QIconItem.ActiveState : QIconItem.DefaultState
Layout.alignment: Qt.AlignHCenter
}
Label {
text: model.caption
Layout.fillWidth: true
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
color: isCurrent ? FishUI.Theme.highlightedTextColor : FishUI.Theme.textColor
}
}
} // GridView.delegate
highlight: Item {
id: highlightItem
Rectangle {
anchors.fill: parent
anchors.margins: FishUI.Units.largeSpacing
radius: _background.radius
color: FishUI.Theme.highlightColor
opacity: 0.7
}
}
Connections {
target: tabBox
function onCurrentIndexChanged() {
thumbnailGridView.currentIndex = tabBox.currentIndex
}
}
} // GridView
// This doesn't work, nor does keyboard input work on any other tabbox skin (KDE 5.7.4)
// It does work in the preview however.
Keys.onPressed: {
console.log('keyPressed', event.key)
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
}