| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Quick Controls module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| import QtQuick 2.2 |
| import QtQuick.Controls 1.3 |
| import QtQuick.Controls.Private 1.0 |
| import QtQuick.Controls.Styles 1.1 |
| import QtQuick.Window 2.1 |
| |
| BasicTableView { |
| id: root |
| |
| property var model |
| |
| readonly property int rowCount: __listView.count |
| property alias currentRow: root.__currentRow |
| |
| signal activated(int row) |
| signal clicked(int row) |
| signal doubleClicked(int row) |
| signal pressAndHold(int row) |
| |
| function positionViewAtRow(row, mode) { |
| __listView.positionViewAtIndex(row, mode) |
| } |
| |
| function rowAt(x, y) { |
| var obj = root.mapToItem(__listView.contentItem, x, y) |
| return __listView.indexAt(obj.x, obj.y) |
| } |
| |
| readonly property alias selection: selectionObject |
| |
| style: Settings.styleComponent(Settings.style, "TableViewStyle.qml", root) |
| |
| Accessible.role: Accessible.Table |
| |
| // Internal stuff. Do not look |
| |
| onModelChanged: selection.clear() |
| |
| __viewTypeName: "TableView" |
| __model: model |
| |
| __itemDelegateLoader: TableViewItemDelegateLoader { |
| __style: root.__style |
| __itemDelegate: root.itemDelegate |
| __mouseArea: mousearea |
| } |
| |
| __mouseArea: MouseArea { |
| id: mousearea |
| |
| parent: __listView |
| width: __listView.width |
| height: __listView.height |
| z: -1 |
| propagateComposedEvents: true |
| focus: true |
| |
| property bool autoincrement: false |
| property bool autodecrement: false |
| property int previousRow: 0 |
| property int clickedRow: -1 |
| property int dragRow: -1 |
| property int firstKeyRow: -1 |
| property int pressedRow: -1 |
| property int pressedColumn: -1 |
| |
| TableViewSelection { |
| id: selectionObject |
| } |
| |
| function selected(rowIndex) { |
| if (dragRow > -1 && (rowIndex >= clickedRow && rowIndex <= dragRow |
| || rowIndex <= clickedRow && rowIndex >= dragRow)) |
| return selection.contains(clickedRow) |
| |
| return selection.count && selection.contains(rowIndex) |
| } |
| |
| onReleased: { |
| pressedRow = -1 |
| pressedColumn = -1 |
| autoincrement = false |
| autodecrement = false |
| var clickIndex = __listView.indexAt(0, mouseY + __listView.contentY) |
| if (clickIndex > -1) { |
| if (Settings.hasTouchScreen) { |
| __listView.currentIndex = clickIndex |
| mouseSelect(clickIndex, mouse.modifiers) |
| } |
| previousRow = clickIndex |
| } |
| |
| if (mousearea.dragRow >= 0) { |
| selection.__select(selection.contains(mousearea.clickedRow), mousearea.clickedRow, mousearea.dragRow) |
| mousearea.dragRow = -1 |
| } |
| } |
| |
| function decrementCurrentIndex() { |
| __listView.decrementCurrentIndexBlocking(); |
| |
| var newIndex = __listView.indexAt(0, __listView.contentY) |
| if (newIndex !== -1) { |
| if (selectionMode > SelectionMode.SingleSelection) |
| mousearea.dragRow = newIndex |
| else if (selectionMode === SelectionMode.SingleSelection) |
| selection.__selectOne(newIndex) |
| } |
| } |
| |
| function incrementCurrentIndex() { |
| __listView.incrementCurrentIndexBlocking(); |
| |
| var newIndex = Math.max(0, __listView.indexAt(0, __listView.height + __listView.contentY)) |
| if (newIndex !== -1) { |
| if (selectionMode > SelectionMode.SingleSelection) |
| mousearea.dragRow = newIndex |
| else if (selectionMode === SelectionMode.SingleSelection) |
| selection.__selectOne(newIndex) |
| } |
| } |
| |
| // Handle vertical scrolling whem dragging mouse outside boundraries |
| Timer { |
| running: mousearea.autoincrement && __verticalScrollBar.visible |
| repeat: true |
| interval: 20 |
| onTriggered: mousearea.incrementCurrentIndex() |
| } |
| |
| Timer { |
| running: mousearea.autodecrement && __verticalScrollBar.visible |
| repeat: true |
| interval: 20 |
| onTriggered: mousearea.decrementCurrentIndex() |
| } |
| |
| onPositionChanged: { |
| if (mouseY > __listView.height && pressed) { |
| if (autoincrement) return; |
| autodecrement = false; |
| autoincrement = true; |
| } else if (mouseY < 0 && pressed) { |
| if (autodecrement) return; |
| autoincrement = false; |
| autodecrement = true; |
| } else { |
| autoincrement = false; |
| autodecrement = false; |
| } |
| |
| if (pressed && containsMouse) { |
| pressedRow = Math.max(0, __listView.indexAt(0, mouseY + __listView.contentY)) |
| pressedColumn = __listView.columnAt(mouseX) |
| if (!Settings.hasTouchScreen) { |
| if (pressedRow >= 0 && pressedRow !== currentRow) { |
| __listView.currentIndex = pressedRow; |
| if (selectionMode === SelectionMode.SingleSelection) { |
| selection.__selectOne(pressedRow) |
| } else if (selectionMode > 1) { |
| dragRow = pressedRow |
| } |
| } |
| } |
| } |
| } |
| |
| onClicked: { |
| var clickIndex = __listView.indexAt(0, mouseY + __listView.contentY) |
| if (clickIndex > -1) { |
| if (root.__activateItemOnSingleClick) |
| root.activated(clickIndex) |
| root.clicked(clickIndex) |
| } |
| } |
| |
| onPressed: { |
| pressedRow = __listView.indexAt(0, mouseY + __listView.contentY) |
| pressedColumn = __listView.columnAt(mouseX) |
| __listView.forceActiveFocus() |
| if (pressedRow > -1 && !Settings.hasTouchScreen) { |
| __listView.currentIndex = pressedRow |
| mouseSelect(pressedRow, mouse.modifiers) |
| mousearea.clickedRow = pressedRow |
| } |
| } |
| |
| onExited: { |
| mousearea.pressedRow = -1 |
| mousearea.pressedColumn = -1 |
| } |
| |
| onCanceled: { |
| mousearea.pressedRow = -1 |
| mousearea.pressedColumn = -1 |
| } |
| |
| function mouseSelect(index, modifiers) { |
| if (selectionMode) { |
| if (modifiers & Qt.ShiftModifier && (selectionMode === SelectionMode.ExtendedSelection)) { |
| selection.select(previousRow, index) |
| } else if (selectionMode === SelectionMode.MultiSelection || |
| (selectionMode === SelectionMode.ExtendedSelection && modifiers & Qt.ControlModifier)) { |
| selection.__select(!selection.contains(index) , index) |
| } else { |
| selection.__selectOne(index) |
| } |
| } |
| } |
| |
| onDoubleClicked: { |
| var clickIndex = __listView.indexAt(0, mouseY + __listView.contentY) |
| if (clickIndex > -1) { |
| if (!root.__activateItemOnSingleClick) |
| root.activated(clickIndex) |
| root.doubleClicked(clickIndex) |
| } |
| } |
| |
| onPressAndHold: { |
| var pressIndex = __listView.indexAt(0, mouseY + __listView.contentY) |
| if (pressIndex > -1) |
| root.pressAndHold(pressIndex) |
| } |
| |
| // Note: with boolean preventStealing we are keeping the flickable from |
| // eating our mouse press events |
| preventStealing: !Settings.hasTouchScreen |
| |
| function keySelect(shiftPressed, row) { |
| if (row < 0 || row > rowCount - 1) |
| return |
| if (shiftPressed && (selectionMode >= SelectionMode.ExtendedSelection)) { |
| selection.__ranges = new Array() |
| selection.select(mousearea.firstKeyRow, row) |
| } else { |
| selection.__selectOne(row) |
| } |
| } |
| |
| Keys.forwardTo: [root] |
| |
| Keys.onUpPressed: { |
| event.accepted = __listView.decrementCurrentIndexBlocking() |
| if (selectionMode) |
| keySelect(event.modifiers & Qt.ShiftModifier, currentRow) |
| } |
| |
| Keys.onDownPressed: { |
| event.accepted = __listView.incrementCurrentIndexBlocking() |
| if (selectionMode) |
| keySelect(event.modifiers & Qt.ShiftModifier, currentRow) |
| } |
| |
| Keys.onPressed: { |
| __listView.scrollIfNeeded(event.key) |
| |
| if (event.key === Qt.Key_Shift) { |
| firstKeyRow = currentRow |
| } |
| |
| if (event.key === Qt.Key_A && event.modifiers & Qt.ControlModifier) { |
| if (selectionMode > 1) |
| selection.selectAll() |
| } |
| } |
| |
| Keys.onReleased: { |
| if (event.key === Qt.Key_Shift) |
| firstKeyRow = -1 |
| } |
| |
| Keys.onReturnPressed: { |
| if (currentRow > -1) |
| root.activated(currentRow); |
| else |
| event.accepted = false |
| } |
| } |
| } |