320 lines
11 KiB
QML
320 lines
11 KiB
QML
|
/****************************************************************************
|
||
|
**
|
||
|
** 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
|
||
|
}
|
||
|
}
|
||
|
}
|