/*SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org>SPDX-License-Identifier: GPL-2.0-or-later*/pragma ComponentBehavior: Boundimport QtQuickimport org.kde.kirigami as Kirigamiimport org.kde.ksvg as KSvgimport org.kde.plasma.components as PlasmaComponentsimport org.kde.plasma.private.kicker as KickerPlasmaComponents.ScrollView {id: itemMultiGridsignal interactionConcluded()anchors {top: parent.top}width: parent.widthimplicitHeight: itemColumn.implicitHeightsignal keyNavLeft(int subGridIndex)signal keyNavRight(int subGridIndex)signal keyNavUp()signal keyNavDown()property int cellSizeproperty int iconSizeproperty alias model: repeater.modelproperty alias count: repeater.countproperty alias flickableItem: flickableproperty ItemGridView firstGridfunction subGridAt(index) {let subgrid = repeater.itemAt(index)if (subgrid) {return subgrid.itemGrid}}function selectFirstElement() {let foundAny = falsefor (var i = 0; i < repeater.count; i++) {let grid = subGridAt(i)if (grid && grid.count > 0) {if (!foundAny) {itemMultiGrid.firstGrid = gridgrid.currentIndex = 0foundAny = true} else {grid.currentIndex = -1}}}}function tryActivate(row, col) { // FIXME TODO: Cleanup messy algo.if (flickable.contentY > 0) {row = 0;}var target = null;var rows = 0;for (var i = 0; i < repeater.count; i++) {var grid = subGridAt(i);if (rows <= row) {target = grid;rows += grid.lastRow() + 2; // Header counts as one.} else {break;}}if (target) {rows -= (target.lastRow() + 2);target.tryActivate(row - rows, col);}}onFocusChanged: {if (!focus) {for (var i = 0; i < repeater.count; i++) {subGridAt(i).focus = false;}}}Flickable {id: flickableflickableDirection: Flickable.VerticalFlickcontentHeight: itemColumn.implicitHeightColumn {id: itemColumnwidth: itemMultiGrid.width - Kirigami.Units.gridUnitRepeater {id: repeaterdelegate: Item {id: gridDelegaterequired property int indexwidth: itemColumn.width - Kirigami.Units.gridUnitheight: headerHeight + gridView.height + (index == repeater.count - 1 ? 0 : footerHeight)readonly property int headerHeight: (gridViewLabel.height+ gridViewLabelUnderline.height + Kirigami.Units.gridUnit)readonly property int footerHeight: (Math.ceil(headerHeight / itemMultiGrid.cellSize) * itemMultiGrid.cellSize) - headerHeightproperty alias itemGrid: gridViewvisible: gridView.count > 0Kirigami.Heading {id: gridViewLabelanchors.top: parent.topx: Kirigami.Units.smallSpacingwidth: parent.width - xheight: dummyHeading.heightelide: Text.ElideRightwrapMode: Text.NoWrapopacity: 1.0color: "white" // FIXME TODO: Respect theming?level: 1text: repeater.model.modelForRow(gridDelegate.index).descriptiontextFormat: Text.PlainText}KSvg.SvgItem {id: gridViewLabelUnderlineanchors.top: gridViewLabel.bottomwidth: parent.width - Kirigami.Units.gridUnitimagePath: "widgets/line"elementId: "horizontal-line"}TapHandler {onTapped: itemMultiGrid.interactionConcluded()}ItemGridView {id: gridViewanchors {top: gridViewLabelUnderline.bottomtopMargin: Kirigami.Units.gridUnit}width: parent.widthheight: Math.ceil(count / Math.floor(width / itemMultiGrid.cellSize)) * itemMultiGrid.cellSizecellWidth: itemMultiGrid.cellSizecellHeight: itemMultiGrid.cellSizeiconSize: itemMultiGrid.iconSizehoverEnabled: itemMultiGrid.hoverEnabledmodel: repeater.model.modelForRow(gridDelegate.index)onFocusChanged: {if (focus) {itemMultiGrid.focus = true;}}onInteractionConcluded: itemMultiGrid.interactionConcluded()onCountChanged: itemMultiGrid.selectFirstElement()onCurrentItemChanged: {if (!currentItem) {return;}if (gridDelegate.index == 0 && currentRow() === 0) {flickable.contentY = 0;return;}var y = currentItem.y;y = contentItem.mapToItem(flickable.contentItem, 0, y).y;if (y < flickable.contentY) {flickable.contentY = y;} else {y += itemMultiGrid.cellSize;y -= flickable.contentY;y -= itemMultiGrid.height;if (y > 0) {flickable.contentY += y;}}}onKeyNavLeft: {itemMultiGrid.keyNavLeft(gridDelegate.index);currentIndex = -1}onKeyNavRight: {itemMultiGrid.keyNavRight(gridDelegate.index);currentIndex = -1}onKeyNavUp: {if (gridDelegate.index > 0) {for (var i = gridDelegate.index - 1; i >= 0; i--) {if (itemMultiGrid.subGridAt(i).count > 0) {itemMultiGrid.subGridAt(i).tryActivate(itemMultiGrid.subGridAt(i).lastRow(), currentCol());break;}}} else {itemMultiGrid.keyNavUp();}currentIndex = -1}onKeyNavDown: {if (gridDelegate.index < repeater.count - 1) {for (let i = gridDelegate.index + 1; i < repeater.count; i++) {if (itemMultiGrid.subGridAt(i).count > 0) {itemMultiGrid.subGridAt(i).tryActivate(0, currentCol());break;}}} else {itemMultiGrid.keyNavDown();}currentIndex = -1}Keys.onBacktabPressed: event => {currentIndex = -1event.accepted = false // pass to mainColumn handler}}// HACK: Steal wheel events from the nested grid view and forward them to// the ScrollView's internal WheelArea.Kicker.WheelInterceptor {anchors.fill: gridViewz: 1destination: findWheelArea(itemMultiGrid)}}}}}}