/**************************************************************************** Copyright (C) 2015 by Eike Hein <hein@kde.org> ** Copyright (C) 2021 by Mikel Johnson <mikel5764@gmail.com> ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the ** Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ****************************************************************************/import QtQuick 2.4import org.kde.plasma.core 2.0 as PlasmaCoreimport org.kde.plasma.components 3.0 as PC3FocusScope {id: itemGridfunction keyNavLeft() {if (itemGrid.currentCol() !== 0) {if (LayoutMirroring.enabled) {gridView.moveCurrentIndexRight();} else {gridView.moveCurrentIndexLeft();}return true;} else {return false;}}function keyNavRight() {if (itemGrid.currentCol() !== columns - 1 && gridView.currentIndex != gridView.count -1) {if (LayoutMirroring.enabled) {gridView.moveCurrentIndexLeft();} else {gridView.moveCurrentIndexRight();}return true;} else {return false;}}function keyNavUp() {if (itemGrid.currentRow() !== 0) {gridView.moveCurrentIndexUp();gridView.positionViewAtIndex(gridView.currentIndex, GridView.Contain);return true;} else {return false;}}function keyNavDown() {if (itemGrid.currentRow() < itemGrid.lastRow()) {//Fix moveCurrentIndexDown()'s lack of proper spatial nav down//into partial columns.var newIndex = gridView.currentIndex + columns;gridView.currentIndex = Math.min(newIndex, gridView.count - 1);gridView.positionViewAtIndex(gridView.currentIndex, GridView.Contain);return true;} else {return false;}}readonly property Item gridView: gridViewproperty alias currentIndex: gridView.currentIndexproperty alias currentItem: gridView.currentItemproperty alias contentItem: gridView.contentItemproperty alias count: gridView.countproperty alias model: gridView.modelproperty alias cellWidth: gridView.cellWidthproperty alias cellHeight: gridView.cellHeightproperty alias iconSize: gridView.iconSizeproperty alias contentHeight: gridView.contentHeightproperty alias interactive: gridView.interactiveproperty alias move: gridView.moveproperty alias moveDisplaced: gridView.moveDisplaced// NOTE: We don't name panes because doing so would be annoying and redundantAccessible.role: Accessible.ParagraphAccessible.name: i18n("Grid with %1 rows, %2 columns", rows, columns) // can't use i18np hereonFocusChanged: {if (!focus) {currentIndex = 0;}}Connections {target: plasmoidfunction onExpandedChanged() {if (!plasmoid.expanded) {gridView.positionAtBeginning();}}}property int columns: Math.floor(width / itemGrid.cellWidth);property int rows: Math.ceil(count / columns);function currentRow() {if (currentIndex == -1) {return -1;}return Math.floor(currentIndex / Math.floor(width / itemGrid.cellWidth));}function currentCol() {if (currentIndex == -1) {return -1;}return currentIndex - (currentRow() * Math.floor(width / itemGrid.cellWidth));}function lastRow() {return Math.ceil(count / columns) - 1;}function tryActivate(row, col) {if (count) {row = Math.min(row, rows - 1);col = Math.min(col, columns - 1);currentIndex = Math.min(row ? ((Math.max(1, row) * columns) + col): col,count - 1);focus = true;}}function forceLayout() {gridView.forceLayout();}ActionMenu {id: actionMenuonActionClicked: {visualParent.actionTriggered(actionId, actionArgument);}}PC3.ScrollView {anchors.fill: parentPC3.ScrollBar.horizontal.visible: falsefocus: trueGridView {id: gridViewproperty int iconSize: PlasmaCore.Units.iconSizes.largeproperty bool animating: falsecellWidth: gridView.iconSize + PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).height+ (4 * PlasmaCore.Units.smallSpacing + Math.round(PlasmaCore.Units.smallSpacing * 1.5)) //item margins + spacing+ (2 * gridView.cellMargin) //highlight padding+ cellMargin * 2 //actual marginscellHeight: cellWidthproperty int cellMargin: Math.round(PlasmaCore.Units.smallSpacing * 1.5)leftMargin: LayoutMirroring.enabled ? 0 : Math.round((parent.width-cellWidth*Math.floor(parent.width / cellWidth))/2)rightMargin: LayoutMirroring.enabled ? Math.round((parent.width-cellWidth*Math.floor(parent.width / cellWidth))/2) : 0topMargin: Math.round(PlasmaCore.Units.smallSpacing * 0.25)bottomMargin: (contentHeight + topMargin) > parent.height ? Math.round(PlasmaCore.Units.smallSpacing * 0.25) : 0focus: true// Let root handle keyboard interactionKeys.forwardTo: [root]currentIndex: 0function positionAtBeginning() {positionViewAtBeginning();// positionViewAtBeginning doesn't account for margins// move content manually only if it overflowsif (visibleArea.heightRatio !== 1.0) {contentY -= topMargin;}currentIndex = 0;}keyNavigationWraps: falseboundsBehavior: Flickable.StopAtBoundsdelegate: KickoffGridItem { }PC3.ToolTip {parent: gridView.currentItem ? gridView.currentItem : gridViewvisible: itemGrid.parent == root.currentContentView && gridView.currentItem ? gridView.currentItem.labelTruncated && ((navigationMethod.state == "keyboard" && keyboardNavigation.state == "RightColumn" && itemGrid.activeFocus) || hoverArea.containsMouse) : falsetext: gridView.currentItem ? gridView.currentItem.display : ""}highlight: Item {opacity: navigationMethod.state != "keyboard" || (keyboardNavigation.state == "RightColumn" && gridView.activeFocus) ? 1 : 0.5PlasmaCore.FrameSvgItem {visible: gridView.currentItemanchors.fill: parentanchors.margins: gridView.cellMarginimagePath: "widgets/viewitem"prefix: "hover"}}highlightFollowsCurrentItem: truehighlightMoveDuration: 0onModelChanged: {currentIndex = 0;}MouseArea {anchors.left: parent.leftwidth: parent.widthheight: parent.heightid: hoverAreaproperty Item pressed: nullproperty int pressX: -1property int pressY: -1property bool tapAndHold: falsehoverEnabled: trueacceptedButtons: Qt.LeftButton | Qt.RightButtononPressed: {var mapped = gridView.mapToItem(gridView.contentItem, mouse.x, mouse.y);var item = gridView.itemAt(mapped.x, mapped.y);if (!item) {return;}if (mouse.buttons & Qt.RightButton) {if (item.hasActionList) {mapped = gridView.contentItem.mapToItem(item, mapped.x, mapped.y);gridView.currentItem.openActionMenu(mapped.x, mapped.y);}} else {pressed = item;pressX = mouse.x;pressY = mouse.y;}}onReleased: {var mapped = gridView.mapToItem(gridView.contentItem, mouse.x, mouse.y);var item = gridView.itemAt(mapped.x, mapped.y);if (item && pressed === item && !tapAndHold) {if (item.appView) {if (mouse.source == Qt.MouseEventSynthesizedByQt) {positionChanged(mouse);}if (isManagerMode && view.currentItem && !view.currentItem.modelChildren) {view.activatedItem = view.currentItem;view.moveRight();} else if (!isManagerMode) {view.state = "OutgoingLeft";}} else {item.activate();}}if (tapAndHold && mouse.source == Qt.MouseEventSynthesizedByQt) {if (item.hasActionList) {mapped = gridView.contentItem.mapToItem(item, mapped.x, mapped.y);gridView.currentItem.openActionMenu(mapped.x, mapped.y);}}pressed = null;pressX = -1;pressY = -1;tapAndHold = false;}onPositionChanged: {var mapped = gridView.mapToItem(gridView.contentItem, mouse.x, mouse.y);var item = gridView.itemAt(mapped.x, mapped.y);if (item) {navigationMethod.state = "mouse"keyboardNavigation.state = "RightColumn"if (kickoff.dragSource == null || kickoff.dragSource == item) {gridView.currentIndex = item.itemIndex;}}if (mouse.source != Qt.MouseEventSynthesizedByQt || tapAndHold) {if (pressed && pressX != -1 && pressed.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) {kickoff.dragSource = item;if (mouse.source == Qt.MouseEventSynthesizedByQt) {dragHelper.dragIconSize = PlasmaCore.Units.iconSizes.hugedragHelper.startDrag(kickoff, pressed.url, pressed.decoration);} else {dragHelper.dragIconSize = PlasmaCore.Units.iconSizes.mediumdragHelper.startDrag(kickoff, pressed.url, pressed.decoration);}pressed = null;pressX = -1;pressY = -1;tapAndHold = false;}}}onContainsMouseChanged: {if (!containsMouse) {pressed = null;pressX = -1;pressY = -1;tapAndHold = false;}}onPressAndHold: {if (mouse.source == Qt.MouseEventSynthesizedByQt) {tapAndHold = true;positionChanged(mouse);}}}}}}