692 lines
25 KiB
QML
692 lines
25 KiB
QML
// Copyright (C) 2018 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
import QtQuick
|
|
import QtQuick.Window
|
|
import QtQml.Models
|
|
import TestTableModel
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import Qt.labs.qmlmodels
|
|
|
|
ApplicationWindow {
|
|
id: window
|
|
width: 1000
|
|
height: 600
|
|
visible: true
|
|
|
|
readonly property var currentIndex: tableView.selectionModel.currentIndex
|
|
readonly property point positionOffset: useOffset.checked ? Qt.point(10, 10) : Qt.point(0, 0)
|
|
readonly property rect positionSubRect: useSubRect.checked ? Qt.rect(10, 10, 10, 10) : Qt.rect(0, 0, 0, 0)
|
|
property int hiddenColumn: -1
|
|
|
|
ScrollView {
|
|
id: menu
|
|
height: window.height
|
|
width: 230
|
|
|
|
readonly property real menuMargin: 10
|
|
|
|
ColumnLayout {
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.topMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
ColumnLayout {
|
|
CheckBox {
|
|
text: "Use Syncview"
|
|
checkable: true
|
|
checked: true
|
|
Layout.fillWidth: false
|
|
onCheckedChanged: {
|
|
if (checked) {
|
|
leftHeader.syncView = tableView
|
|
topHeader.syncView = tableView
|
|
} else {
|
|
leftHeader.syncView = null
|
|
topHeader.syncView = null
|
|
}
|
|
}
|
|
}
|
|
|
|
CheckBox {
|
|
id: flickingMode
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Interactive"
|
|
}
|
|
|
|
CheckBox {
|
|
id: indexNavigation
|
|
checkable: true
|
|
checked: true
|
|
Layout.fillWidth: false
|
|
text: "Enable navigation"
|
|
}
|
|
|
|
CheckBox {
|
|
id: resizableRowsEnabled
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Resizable rows"
|
|
}
|
|
|
|
CheckBox {
|
|
id: resizableColumnsEnabled
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Resizable columns"
|
|
}
|
|
|
|
CheckBox {
|
|
id: movableColumnEnabled
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Reorder columns"
|
|
}
|
|
|
|
CheckBox {
|
|
id: movableRowEnabled
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Reorder rows"
|
|
}
|
|
|
|
CheckBox {
|
|
id: enableAnimation
|
|
checkable: true
|
|
checked: true
|
|
Layout.fillWidth: false
|
|
text: "Enable animation"
|
|
}
|
|
|
|
CheckBox {
|
|
id: drawText
|
|
checkable: true
|
|
checked: true
|
|
Layout.fillWidth: false
|
|
text: "Draw text"
|
|
}
|
|
|
|
CheckBox {
|
|
id: useRandomColor
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Use colors"
|
|
}
|
|
|
|
CheckBox {
|
|
id: useLargeCells
|
|
checkable: true
|
|
checked: false
|
|
text: "Use large cells"
|
|
Layout.fillWidth: false
|
|
onCheckedChanged: Qt.callLater(tableView.forceLayout)
|
|
}
|
|
|
|
CheckBox {
|
|
id: useSubRect
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Use subRect"
|
|
}
|
|
|
|
CheckBox {
|
|
id: useOffset
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Use offset"
|
|
}
|
|
|
|
CheckBox {
|
|
id: highlightCurrentRow
|
|
checkable: true
|
|
checked: false
|
|
Layout.fillWidth: false
|
|
text: "Highlight row/col"
|
|
}
|
|
|
|
CheckBox {
|
|
id: showSelectionHandles
|
|
checkable: true
|
|
checked: tableView.interactive
|
|
text: "Show selection handles"
|
|
Layout.fillWidth: false
|
|
}
|
|
|
|
ComboBox {
|
|
id: selectionCombo
|
|
currentIndex: 1
|
|
model: [
|
|
"SelectionDisabled",
|
|
"SelectCells",
|
|
"SelectRows",
|
|
"SelectColumns",
|
|
]
|
|
Layout.fillWidth: false
|
|
}
|
|
|
|
ComboBox {
|
|
id: selectionModeTv
|
|
textRole: "text"
|
|
valueRole: "value"
|
|
implicitContentWidthPolicy: ComboBox.WidestText
|
|
currentIndex: 2
|
|
model: [
|
|
{ text: "SingleSelection", value: TableView.SingleSelection },
|
|
{ text: "ContiguousSelection", value: TableView.ContiguousSelection },
|
|
{ text: "ExtendedSelection", value: TableView.ExtendedSelection }
|
|
]
|
|
Layout.fillWidth: false
|
|
}
|
|
|
|
ComboBox {
|
|
id: selectionModeCombo
|
|
enabled: selectionCombo.currentText != "SelectionDisabled"
|
|
model: [
|
|
"Auto",
|
|
"Drag",
|
|
"PressAndHold",
|
|
]
|
|
Layout.fillWidth: false
|
|
}
|
|
ComboBox {
|
|
id: editCombo
|
|
currentIndex: 2
|
|
model: [
|
|
"NoEditTriggers",
|
|
"SingleTapped",
|
|
"DoubleTapped",
|
|
"SelectedTapped",
|
|
"EditKeyPressed",
|
|
"AnyKeyPressed",
|
|
]
|
|
Layout.fillWidth: false
|
|
}
|
|
Button {
|
|
text: "Clear selection"
|
|
onClicked: tableView.selectionModel.clearSelection()
|
|
}
|
|
Button {
|
|
text: "Clear column reordering"
|
|
onClicked: tableView.clearColumnReordering()
|
|
}
|
|
Button {
|
|
text: "Clear row reordering"
|
|
onClicked: tableView.clearRowReordering()
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
GridLayout {
|
|
columns: 2
|
|
Label { text: "Model size:" }
|
|
SpinBox {
|
|
id: modelSize
|
|
from: 0
|
|
to: 1000
|
|
value: 200
|
|
editable: true
|
|
Layout.fillWidth: false
|
|
}
|
|
Label { text: "Spacing:" }
|
|
SpinBox {
|
|
id: spaceSpinBox
|
|
from: -100
|
|
to: 100
|
|
value: 1
|
|
editable: true
|
|
Layout.fillWidth: false
|
|
}
|
|
Label { text: "Margins:" }
|
|
SpinBox {
|
|
id: marginsSpinBox
|
|
from: 0
|
|
to: 100
|
|
value: 0
|
|
editable: true
|
|
Layout.fillWidth: false
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
RowLayout {
|
|
id: positionRow
|
|
Button {
|
|
text: "<<"
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
tableView.positionViewAtRow(0, Qt.AlignTop, -tableView.topMargin)
|
|
tableView.positionViewAtColumn(0, Qt.AlignLeft, -tableView.leftMargin)
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: ">>"
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
tableView.positionViewAtRow(tableView.rows - 1, Qt.AlignBottom, tableView.bottomMargin)
|
|
tableView.positionViewAtColumn(tableView.columns - 1, Qt.AlignRight, tableView.rightMargin)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
ColumnLayout {
|
|
Button {
|
|
text: "Add row"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: tableView.model.insertRows(currentIndex.row, 1)
|
|
}
|
|
|
|
Button {
|
|
text: "Remove row"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: tableView.model.removeRows(currentIndex.row, 1)
|
|
}
|
|
|
|
Button {
|
|
text: "Add column"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: tableView.model.insertColumns(currentIndex.column, 1)
|
|
}
|
|
|
|
Button {
|
|
text: "Remove column"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: tableView.model.removeColumns(currentIndex.column, 1)
|
|
}
|
|
|
|
Button {
|
|
text: "Hide column"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
hiddenColumn = currentIndex.column
|
|
tableView.forceLayout()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
ColumnLayout {
|
|
Button {
|
|
text: "Current to top-left"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let cell = Qt.point(currentIndex.column, currentIndex.row)
|
|
tableView.positionViewAtCell(cell, Qt.AlignTop | Qt.AlignLeft, positionOffset, positionSubRect)
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "Current to center"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let cell = Qt.point(currentIndex.column, currentIndex.row)
|
|
tableView.positionViewAtCell(cell, Qt.AlignCenter, positionOffset, positionSubRect)
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "Current to bottom-right"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let cell = Qt.point(currentIndex.column, currentIndex.row)
|
|
tableView.positionViewAtCell(cell, Qt.AlignBottom | Qt.AlignRight, positionOffset, positionSubRect)
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "Current to Visible"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let cell = Qt.point(currentIndex.column, currentIndex.row)
|
|
tableView.positionViewAtCell(cell, TableView.Visible, positionOffset, positionSubRect)
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "Current to Contain"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let cell = Qt.point(currentIndex.column, currentIndex.row)
|
|
tableView.positionViewAtCell(cell, TableView.Contain, positionOffset, positionSubRect)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
ColumnLayout {
|
|
Button {
|
|
text: "Open editor"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
tableView.edit(currentIndex, true)
|
|
}
|
|
}
|
|
Button {
|
|
text: "Close editor"
|
|
enabled: currentIndex.valid
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
tableView.closeEditor()
|
|
}
|
|
}
|
|
Button {
|
|
text: "Set current index"
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
let index = tableView.modelIndex(1, 1);
|
|
tableView.selectionModel.setCurrentIndex(index, ItemSelectionModel.NoUpdate)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupBox {
|
|
Layout.minimumWidth: menu.availableWidth - (menu.menuMargin * 2)
|
|
Layout.rightMargin: menu.menuMargin
|
|
Layout.leftMargin: menu.menuMargin
|
|
Layout.bottomMargin: menu.menuMargin
|
|
Layout.fillWidth: false
|
|
Layout.fillHeight: false
|
|
ColumnLayout {
|
|
Button {
|
|
text: "Fast-flick table"
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
tableView.contentX += tableView.width * 1.2
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "Fast-flick headers"
|
|
Layout.fillWidth: false
|
|
onClicked: {
|
|
topHeader.contentX += tableView.width * 1.2
|
|
leftHeader.contentY += tableView.height * 1.2
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: "ForceLayout()"
|
|
Layout.fillWidth: false
|
|
onClicked: tableView.forceLayout()
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
Layout.fillHeight: true
|
|
}
|
|
}
|
|
}
|
|
|
|
HorizontalHeaderView {
|
|
id: topHeader
|
|
objectName: "topHeader"
|
|
anchors.left: centerScrollView.left
|
|
anchors.right: centerScrollView.right
|
|
anchors.top: menu.top
|
|
height: 30
|
|
clip: true
|
|
|
|
model: TestTableModel {
|
|
rowCount: 1
|
|
columnCount: modelSize.value
|
|
}
|
|
|
|
delegate: Rectangle {
|
|
required property bool containsDrag
|
|
implicitHeight: topHeader.height
|
|
implicitWidth: 20
|
|
border.width: containsDrag ? 1 : 0
|
|
border.color: containsDrag ? window.palette.text : window.palette.alternateBase
|
|
color: window.palette.alternateBase
|
|
Label {
|
|
anchors.centerIn: parent
|
|
visible: drawText.checked
|
|
text: column
|
|
font.pointSize: 8
|
|
}
|
|
}
|
|
|
|
columnSpacing: 1
|
|
rowSpacing: 1
|
|
|
|
syncView: tableView
|
|
syncDirection: Qt.Horizontal
|
|
movableColumns: movableColumnEnabled.checked
|
|
resizableColumns: resizableColumnsEnabled.checked
|
|
}
|
|
|
|
VerticalHeaderView {
|
|
id: leftHeader
|
|
objectName: "leftHeader"
|
|
anchors.left: menu.right
|
|
anchors.top: centerScrollView.top
|
|
anchors.bottom: centerScrollView.bottom
|
|
width: 30
|
|
clip: true
|
|
|
|
model: TestTableModel {
|
|
rowCount: modelSize.value
|
|
columnCount: 1
|
|
}
|
|
|
|
delegate: Rectangle {
|
|
required property bool containsDrag
|
|
implicitHeight: 50
|
|
implicitWidth: leftHeader.width
|
|
border.width: containsDrag ? 1 : 0
|
|
border.color: containsDrag ? window.palette.text : window.palette.alternateBase
|
|
color: window.palette.alternateBase
|
|
Label {
|
|
anchors.centerIn: parent
|
|
visible: drawText.checked
|
|
text: row
|
|
font.pointSize: 8
|
|
}
|
|
}
|
|
|
|
columnSpacing: 1
|
|
rowSpacing: 1
|
|
|
|
syncView: tableView
|
|
syncDirection: Qt.Vertical
|
|
movableRows: movableRowEnabled.checked
|
|
resizableRows: resizableRowsEnabled.checked
|
|
}
|
|
|
|
Item {
|
|
id: centerScrollView
|
|
anchors.left: leftHeader.right
|
|
anchors.right: parent.right
|
|
anchors.top: topHeader.bottom
|
|
anchors.bottom: parent.bottom
|
|
anchors.topMargin: 1
|
|
anchors.leftMargin: 1
|
|
anchors.rightMargin: 10
|
|
anchors.bottomMargin: 10
|
|
|
|
TableView {
|
|
id: tableView
|
|
anchors.fill: parent
|
|
objectName: "tableview"
|
|
clip: true
|
|
delegate: tableViewDelegate
|
|
columnSpacing: spaceSpinBox.value
|
|
rowSpacing: spaceSpinBox.value
|
|
interactive: flickingMode.checked
|
|
keyNavigationEnabled: indexNavigation.checked
|
|
pointerNavigationEnabled: indexNavigation.checked
|
|
resizableRows: resizableRowsEnabled.checked
|
|
resizableColumns: resizableColumnsEnabled.checked
|
|
animate: enableAnimation.checked
|
|
selectionBehavior: {
|
|
switch (selectionCombo.currentText) {
|
|
case "SelectCells": return TableView.SelectCells
|
|
case "SelectRows": return TableView.SelectRows
|
|
case "SelectColumns": return TableView.SelectColumns
|
|
}
|
|
return TableView.SelectionDisabled
|
|
}
|
|
selectionMode: selectionModeTv.currentValue
|
|
editTriggers: {
|
|
switch (editCombo.currentText) {
|
|
case "NoEditTriggers": return TableView.NoEditTriggers
|
|
case "SingleTapped": return TableView.SingleTapped
|
|
case "DoubleTapped": return TableView.DoubleTapped
|
|
case "SelectedTapped": return TableView.SelectedTapped
|
|
case "EditKeyPressed": return TableView.EditKeyPressed
|
|
case "AnyKeyPressed": return TableView.AnyKeyPressed
|
|
}
|
|
return TableView.SelectionDisabled
|
|
}
|
|
|
|
leftMargin: marginsSpinBox.value
|
|
topMargin: marginsSpinBox.value
|
|
rightMargin: marginsSpinBox.value
|
|
bottomMargin: marginsSpinBox.value
|
|
|
|
ScrollBar.horizontal: ScrollBar { visible: !flickingMode.checked }
|
|
ScrollBar.vertical: ScrollBar { visible: !flickingMode.checked }
|
|
|
|
model: TestTableModel {
|
|
rowCount: modelSize.value
|
|
columnCount: modelSize.value
|
|
}
|
|
|
|
selectionModel: ItemSelectionModel {}
|
|
}
|
|
}
|
|
|
|
SelectionRectangle {
|
|
id: selectionRectangle
|
|
target: tableView
|
|
enabled: selectionCombo.currentText != "SelectionDisabled"
|
|
topLeftHandle: Rectangle {
|
|
width: 20
|
|
height: 20
|
|
radius: 10
|
|
color: "blue"
|
|
visible: showSelectionHandles.checked && selectionRectangle.active
|
|
}
|
|
|
|
bottomRightHandle: Rectangle {
|
|
width: 20
|
|
height: 20
|
|
radius: 10
|
|
color: "green"
|
|
visible: showSelectionHandles.checked && selectionRectangle.active
|
|
}
|
|
|
|
selectionMode: {
|
|
switch (selectionModeCombo.currentText) {
|
|
case "Drag": return SelectionRectangle.Drag
|
|
case "PressAndHold": return SelectionRectangle.PressAndHold
|
|
}
|
|
return SelectionRectangle.Auto
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: tableViewDelegate
|
|
Rectangle {
|
|
id: delegate
|
|
implicitWidth: useLargeCells.checked ? 1000 : 50
|
|
implicitHeight: useLargeCells.checked ? 1000 : 30
|
|
border.width: current ? 3 : 0
|
|
border.color: window.palette.highlight
|
|
property var randomColor: Qt.rgba(0.6 + (0.4 * Math.random()), 0.6 + (0.4 * Math.random()), 0.6 + (0.4 * Math.random()), 1)
|
|
color: selected ? window.palette.highlight
|
|
: (highlightCurrentRow.checked && (row === tableView.currentRow || column === tableView.currentColumn)) ? "lightgray"
|
|
: useRandomColor.checked ? randomColor
|
|
: model.display === "added" ? "lightblue"
|
|
: window.palette.window.lighter(1.3)
|
|
|
|
required property bool selected
|
|
required property bool current
|
|
required property bool editing
|
|
|
|
Rectangle {
|
|
x: positionSubRect.x
|
|
y: positionSubRect.y
|
|
width: positionSubRect.width
|
|
height: positionSubRect.height
|
|
border.color: "red"
|
|
visible: useSubRect.checked
|
|
}
|
|
|
|
Label {
|
|
anchors.centerIn: parent
|
|
visible: drawText.checked && !editing
|
|
text: model.display
|
|
}
|
|
|
|
TableView.editDelegate: TextField {
|
|
anchors.fill: parent
|
|
horizontalAlignment: TextInput.AlignHCenter
|
|
verticalAlignment: TextInput.AlignVCenter
|
|
text: display
|
|
|
|
TableView.onCommit: display = text
|
|
Component.onCompleted: selectAll()
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|