summaryrefslogtreecommitdiff
path: root/src/controls/TableView.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/controls/TableView.qml')
-rw-r--r--src/controls/TableView.qml350
1 files changed, 241 insertions, 109 deletions
diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml
index ca0df45a..b02a49c0 100644
--- a/src/controls/TableView.qml
+++ b/src/controls/TableView.qml
@@ -65,8 +65,7 @@ import QtQuick.Controls.Styles 1.0
\endcode
You provide title and size of a column header
- by adding a \l TableViewColumn to the default \l header property
- as demonstrated below.
+ by adding a \l TableViewColumn as demonstrated below.
\code
TableView {
@@ -124,26 +123,37 @@ ScrollView {
The default value is \c true. */
property bool headerVisible: true
+ /*! \qmlproperty bool TableView::backgroundVisible
+
+ This property determines if the background should be filled or not.
+
+ The default value is \c true.
+
+ \note The rowDelegate is not affected by this property
+ */
+ property alias backgroundVisible: colorRect.visible
+
/*! This property defines a delegate to draw a specific cell.
In the item delegate you have access to the following special properties:
\list
- \li itemSelected - if the item is currently selected
- \li itemValue - the value or text for this item
- \li itemTextColor - the default text color for an item
- \li row - the index of the row
- \li column - the index of the column
- \li itemElideMode - the elide mode of the column
- \li itemTextAlignment - the horizontal text alignment of the column
+ \li styleData.selected - if the item is currently selected
+ \li styleData.value - the value or text for this item
+ \li styleData.textColor - the default text color for an item
+ \li styleData.row - the index of the row
+ \li styleData.column - the index of the column
+ \li styleData.elideMode - the elide mode of the column
+ \li styleData.textAlignment - the horizontal text alignment of the column
\endlist
+
Example:
\code
itemDelegate: Item {
Text {
anchors.verticalCenter: parent.verticalCenter
- color: itemTextColor
- elide: itemElideMode
- text: itemValue
+ color: styleData.textColor
+ elide: styleData.elideMode
+ text: styleData.value
}
}
\endcode */
@@ -153,20 +163,23 @@ ScrollView {
In the row delegate you have access to the following special properties:
\list
- \li alternateBackground - if the row uses the alternate background color
- \li rowSelected - if the row is currently selected
- \li index - the index of the row
+ \li styleData.alternate - true when the row uses the alternate background color
+ \li styleData.selected - true when the row is currently selected
+ \li styleData.row - the index of the row
\endlist
*/
property Component rowDelegate: __style ? __style.rowDelegate : null
- /*! \qmlproperty color TableView::backgroundColor
+ /*! This property defines a delegate to draw a header.
- This property sets the background color of the viewport.
- The default value is the base color of the SystemPalette. */
- property alias backgroundColor: colorRect.color
-
- /*! This property defines a delegate to draw a header. */
+ In the header delegate you have access to the following special properties:
+ \list
+ \li styleData.value - the value or text for this item
+ \li styleData.column - the index of the column
+ \li styleData.pressed - true when the column is being pressed
+ \li styleData.containsMouse - true when the column is under the mouse
+ \endlist
+ */
property Component headerDelegate: __style ? __style.headerDelegate : null
/*! Index of the current sort column.
@@ -190,9 +203,8 @@ ScrollView {
*/
property int sortIndicatorOrder: Qt.AscendingOrder
- /*! \qmlproperty list<TableViewColumn> TableView::columns
- This property contains the TableViewColumn items */
- default property alias columns: listView.columnheader
+ /*! \internal */
+ default property alias __columns: root.data
/*! \qmlproperty Component TableView::contentHeader
This is the content header of the TableView */
@@ -206,8 +218,9 @@ ScrollView {
The current number of rows */
readonly property alias rowCount: listView.count
- /*! The current number of columns */
- readonly property int columnCount: columns.length
+ /*! \qmlproperty int TableView::columnCount
+ The current number of columns */
+ readonly property alias columnCount: columnModel.count
/*! \qmlproperty string TableView::section.property
\qmlproperty enumeration TableView::section.criteria
@@ -226,10 +239,30 @@ ScrollView {
/*! \internal */
property alias __currentRowItem: listView.currentItem
- /*! \qmlsignal TableView::activated()
- Emitted when the user activates an item by single or double-clicking (depending on the platform).
+ /*! \qmlsignal TableView::activated(int row)
+
+ Emitted when the user activates an item by mouse or keyboard interaction.
+ Mouse activation is triggered by single- or double-clicking, depending on the platform.
+
+ \a row int provides access to the activated row index.
*/
- signal activated
+ signal activated(int row)
+
+ /*! \qmlsignal TableView::clicked(int row)
+
+ Emitted when the user clicks a valid row by single clicking
+
+ \a row int provides access to the clicked row index.
+ */
+ signal clicked(int row)
+
+ /*! \qmlsignal TableView::doubleClicked(int row)
+
+ Emitted when the user double clicks a valid row.
+
+ \a row int provides access to the clicked row index.
+ */
+ signal doubleClicked(int row)
/*!
\qmlmethod TableView::positionViewAtRow( int row, PositionMode mode )
@@ -255,13 +288,13 @@ ScrollView {
Depending on how the model is populated, the model may not be ready when
TableView Component.onCompleted is called. In that case you may need to
- delay the call to positionViewAtRow by using a \l {Timer}.
+ delay the call to positionViewAtRow by using a \l {QtQml::Timer}{Timer}.
\note This method should only be called after the component has completed.
*/
function positionViewAtRow(row, mode) {
- listView.positionViewAtRow(row, mode)
+ listView.positionViewAtIndex(row, mode)
}
/*!
@@ -278,17 +311,89 @@ ScrollView {
return listView.indexAt(obj.x, obj.y)
}
+ /*! Adds a \a column and returns the added column.
+
+ The \a column argument can be an instance of TableViewColumn,
+ or a Component. The component has to contain a TableViewColumn.
+ Otherwise \c null is returned.
+ */
+ function addColumn(column) {
+ return insertColumn(columnCount, column)
+ }
+
+ /*! Inserts a \a column at the given \a index and returns the inserted column.
+
+ The \a column argument can be an instance of TableViewColumn,
+ or a Component. The component has to contain a TableViewColumn.
+ Otherwise \c null is returned.
+ */
+ function insertColumn(index, column) {
+ var object = column
+ if (typeof column['createObject'] === 'function')
+ object = column.createObject(root)
+
+ else if (object.__view) {
+ console.warn("TableView::insertColumn(): you cannot add a column to multiple views")
+ return null
+ }
+ if (index >= 0 && index <= columnCount && object.Accessible.role === Accessible.ColumnHeader) {
+ object.__view = root
+ columnModel.insert(index, {columnItem: object})
+ return object
+ }
+
+ if (object !== column)
+ object.destroy()
+ console.warn("TableView::insertColumn(): invalid argument")
+ return null
+ }
+
+ /*! Removes and destroys a column at the given \a index. */
+ function removeColumn(index) {
+ if (index < 0 || index >= columnCount) {
+ console.warn("TableView::removeColumn(): invalid argument")
+ return
+ }
+ var column = columnModel.get(index).columnItem
+ columnModel.remove(index, 1)
+ column.destroy()
+ }
+
+ /*! Moves a column \a from index \a to another. */
+ function moveColumn(from, to) {
+ if (from < 0 || from >= columnCount || to < 0 || to >= columnCount) {
+ console.warn("TableView::moveColumn(): invalid argument")
+ return
+ }
+ columnModel.move(from, to, 1)
+ }
+
+ /*! Returns the column at the given \a index
+ or \c null if the \a index is invalid. */
+ function getColumn(index) {
+ if (index < 0 || index >= columnCount)
+ return null
+ return columnModel.get(index).columnItem
+ }
+
+ Component.onCompleted: {
+ for (var i = 0; i < __columns.length; ++i) {
+ var column = __columns[i]
+ if (column.Accessible.role === Accessible.ColumnHeader)
+ addColumn(column)
+ }
+ }
style: Qt.createComponent(Settings.style + "/TableViewStyle.qml", root)
Accessible.role: Accessible.Table
- width: 200
- height: 200
+ implicitWidth: 200
+ implicitHeight: 150
frameVisible: true
- __scrollBarTopMargin: Qt.platform.os === "mac" ? headerrow.height : 0
+ __scrollBarTopMargin: Qt.platform.os === "osx" ? headerrow.height : 0
__viewTopMargin: headerrow.height
/*! \internal */
@@ -327,7 +432,7 @@ ScrollView {
id: colorRect
parent: viewport
anchors.fill: parent
- color: palette.base
+ color: __style ? __style.backgroundColor : palette.base
z: -1
}
@@ -362,28 +467,39 @@ ScrollView {
autoincrement = false;
autodecrement = false;
}
- var y = Math.min(listView.contentY + listView.height - 5, Math.max(mouseY + listView.contentY, listView.contentY));
- var newIndex = listView.indexAt(0, y);
- if (newIndex >= 0)
- listView.currentIndex = listView.indexAt(0, y);
+
+ if (pressed) {
+ var newIndex = listView.indexAt(0, mouseY + listView.contentY)
+ if (newIndex >= 0)
+ listView.currentIndex = newIndex;
+ }
}
onClicked: {
- if (root.__activateItemOnSingleClick)
- root.activated()
+ var clickIndex = listView.indexAt(0, mouseY + listView.contentY)
+ if (clickIndex > -1) {
+ if (root.__activateItemOnSingleClick)
+ root.activated(clickIndex)
+ root.clicked(clickIndex)
+ }
mouse.accepted = false
}
onPressed: {
+ var newIndex = listView.indexAt(0, mouseY + listView.contentY)
listView.forceActiveFocus()
- var x = Math.min(listView.contentWidth - 5, Math.max(mouseX + listView.contentX, 0))
- var y = Math.min(listView.contentHeight - 5, Math.max(mouseY + listView.contentY, 0))
- listView.currentIndex = listView.indexAt(x, y)
+ if (newIndex > -1) {
+ listView.currentIndex = newIndex
+ }
}
onDoubleClicked: {
- if (!root.__activateItemOnSingleClick)
- root.activated()
+ var clickIndex = listView.indexAt(0, mouseY + listView.contentY)
+ if (clickIndex > -1) {
+ if (!root.__activateItemOnSingleClick)
+ root.activated(clickIndex)
+ root.doubleClicked(clickIndex)
+ }
}
// Note: with boolean preventStealing we are keeping the flickable from
@@ -395,7 +511,7 @@ ScrollView {
// Fills extra rows with alternate color
Column {
id: rowfiller
- property int rowHeight: listView.contentHeight/count
+ property int rowHeight: count ? listView.contentHeight/count : height
property int paddedRowCount: height/rowHeight
property int count: listView.count
y: listView.contentHeight
@@ -408,21 +524,33 @@ ScrollView {
width: rowfiller.width
height: rowfiller.rowHeight
sourceComponent: root.rowDelegate
- readonly property bool alternateBackground: (index + rowCount) % 2 === 1
- readonly property bool rowSelected: false
+ property QtObject styleData: QtObject {
+ readonly property bool alternate: (index + rowCount) % 2 === 1
+ readonly property bool selected: false
+ readonly property bool hasActiveFocus: root.activeFocus
+ }
readonly property var model: listView.model
readonly property var modelData: null
- readonly property bool hasActiveFocus: root.activeFocus
}
}
}
- property list<TableViewColumn> columnheader
+ ListModel {
+ id: columnModel
+ }
+
highlightFollowsCurrentItem: true
model: root.model
- Keys.onUpPressed: root.__decrementCurrentIndex()
- Keys.onDownPressed: root.__incrementCurrentIndex()
+ Keys.onUpPressed: {
+ event.accepted = false
+ root.__decrementCurrentIndex()
+ }
+
+ Keys.onDownPressed: {
+ event.accepted = false
+ root.__incrementCurrentIndex()
+ }
Keys.onPressed: {
if (event.key === Qt.Key_PageUp) {
@@ -431,7 +559,11 @@ ScrollView {
verticalScrollBar.value = __verticalScrollBar.value + listView.height
}
- Keys.onReturnPressed: root.activated();
+ Keys.onReturnPressed: {
+ event.accepted = false
+ if (currentRow > -1)
+ root.activated(currentRow);
+ }
delegate: Item {
id: rowitem
@@ -439,7 +571,7 @@ ScrollView {
height: rowstyle.height
readonly property int rowIndex: model.index
- readonly property bool alternateBackground: alternatingRowColors && rowIndex % 2 == 1
+ readonly property bool alternate: alternatingRowColors && rowIndex % 2 == 1
readonly property var itemModelData: typeof modelData == "undefined" ? null : modelData
readonly property var itemModel: model
readonly property bool itemSelected: ListView.isCurrentItem
@@ -457,19 +589,21 @@ ScrollView {
// these properties are exposed to the row delegate
// Note: these properties should be mirrored in the row filler as well
- readonly property bool alternateBackground: rowitem.alternateBackground
- readonly property bool rowSelected: rowitem.itemSelected
- readonly property int row: rowitem.rowIndex
+ property QtObject styleData: QtObject {
+ readonly property int row: rowitem.rowIndex
+ readonly property bool alternate: rowitem.alternate
+ readonly property bool selected: rowitem.itemSelected
+ readonly property bool hasActiveFocus: root.activeFocus
+ }
readonly property var model: listView.model
readonly property var modelData: rowitem.itemModelData
- readonly property bool hasActiveFocus: root.activeFocus
}
Row {
id: itemrow
height: parent.height
Repeater {
id: repeater
- model: root.columnCount
+ model: columnModel
Loader {
id: itemDelegateLoader
@@ -482,20 +616,22 @@ ScrollView {
readonly property var model: listView.model
readonly property var modelData: itemModelData
- readonly property var itemValue: __hasModelRole ? itemModel[role] // Qml ListModel and QAbstractItemModel
- : __hasModelDataRole ? modelData[role] // QObjectList / QObject
- : modelData != undefined ? modelData : "" // Models without role
- readonly property bool itemSelected: rowitem.itemSelected
- readonly property color itemTextColor: rowitem.itemTextColor
- readonly property int row: rowitem.rowIndex
- readonly property int column: index
- readonly property int itemElideMode: __column.elideMode
- readonly property int itemTextAlignment: __column.horizontalAlignment
- readonly property string role: __column.role
-
- readonly property TableViewColumn __column: columns[index]
- readonly property bool __hasModelRole: role && itemModel.hasOwnProperty(role)
- readonly property bool __hasModelDataRole: role && modelData && modelData.hasOwnProperty(role)
+ property QtObject styleData: QtObject {
+ readonly property var value: __hasModelRole ? itemModel[role] // Qml ListModel and QAbstractItemModel
+ : __hasModelDataRole ? modelData[role] // QObjectList / QObject
+ : modelData != undefined ? modelData : "" // Models without role
+ readonly property int row: rowitem.rowIndex
+ readonly property int column: index
+ readonly property int elideMode: __column.elideMode
+ readonly property int textAlignment: __column.horizontalAlignment
+ readonly property bool selected: rowitem.itemSelected
+ readonly property color textColor: rowitem.itemTextColor
+ readonly property string role: __column.role
+ }
+
+ readonly property TableViewColumn __column: columnItem
+ readonly property bool __hasModelRole: styleData.role && itemModel.hasOwnProperty(styleData.role)
+ readonly property bool __hasModelDataRole: styleData.role && modelData && modelData.hasOwnProperty(styleData.role)
}
}
onWidthChanged: listView.contentWidth = width
@@ -513,7 +649,7 @@ ScrollView {
anchors.topMargin: viewport.anchors.topMargin
anchors.leftMargin: viewport.anchors.leftMargin
anchors.margins: viewport.anchors.margins
- anchors.rightMargin: __scroller.rightMargin +
+ anchors.rightMargin: (frameVisible ? __scroller.rightMargin : 0) +
(__scroller.outerFrame && __scrollBarTopMargin ? 0 : __verticalScrollBar.width
+ __scroller.scrollBarSpacing + root.__style.padding.right)
@@ -532,12 +668,12 @@ ScrollView {
property int targetIndex: -1
property int dragIndex: -1
- model: columnCount
+ model: columnModel
delegate: Item {
z:-index
- width: columns[index].width
- visible: columns[index].visible
+ width: columnCount == 1 ? viewport.width + __verticalScrollBar.width : modelData.width
+ visible: modelData.visible
height: headerVisible ? headerStyle.height : 0
Loader {
@@ -545,13 +681,12 @@ ScrollView {
sourceComponent: root.headerDelegate
anchors.left: parent.left
anchors.right: parent.right
- property string itemValue: columns[index].title
- property string itemSort: (sortIndicatorVisible && index == sortIndicatorColumn) ? (sortIndicatorOrder == Qt.AscendingOrder ? "up" : "down") : "";
- property bool itemPressed: headerClickArea.pressed
- property bool itemContainsMouse: headerClickArea.containsMouse
- property string itemPosition: columnCount === 1 ? "only" :
- index===columnCount-1 ? "end" :
- index===0 ? "beginning" : ""
+ property QtObject styleData: QtObject {
+ readonly property string value: modelData.title
+ readonly property bool pressed: headerClickArea.pressed
+ readonly property bool containsMouse: headerClickArea.containsMouse
+ readonly property int column: index
+ }
}
Rectangle{
id: targetmark
@@ -576,7 +711,7 @@ ScrollView {
// NOTE: the direction is different from the master branch
// so this indicates that I am using an invalid assumption on item ordering
onPositionChanged: {
- if (pressed) { // only do this while dragging
+ if (pressed && columnCount > 1) { // only do this while dragging
for (var h = columnCount-1 ; h >= 0 ; --h) {
if (drag.target.x > headerrow.children[h].x) {
repeater.targetIndex = h
@@ -593,13 +728,7 @@ ScrollView {
onReleased: {
if (repeater.targetIndex >= 0 && repeater.targetIndex != index ) {
- // Rearrange the header sections
- var items = new Array
- for (var i = 0 ; i< columnCount ; ++i)
- items.push(columns[i])
- items.splice(index, 1);
- items.splice(repeater.targetIndex, 0, columns[index]);
- columns = items
+ columnModel.move(index, repeater.targetIndex, 1)
if (sortIndicatorColumn == index)
sortIndicatorColumn = repeater.targetIndex
}
@@ -607,19 +736,20 @@ ScrollView {
}
drag.maximumX: 1000
drag.minimumX: -1000
- drag.target: draghandle
+ drag.target: columnCount > 1 ? draghandle : null
}
Loader {
id: draghandle
- property string itemValue: columns[index].title
- property string itemSort: (sortIndicatorVisible && index == sortIndicatorColumn) ? (sortIndicatorOrder == Qt.AscendingOrder ? "up" : "down") : "";
- property bool itemPressed: headerClickArea.pressed
- property bool itemContainsMouse: headerClickArea.containsMouse
- property string itemPosition
+ property QtObject styleData: QtObject{
+ readonly property string value: modelData.title
+ readonly property bool pressed: headerClickArea.pressed
+ readonly property bool containsMouse: headerClickArea.containsMouse
+ readonly property int column: index
+ }
parent: tableHeader
- width: columns[index].width
+ width: modelData.width
height: parent.height
sourceComponent: root.headerDelegate
visible: headerClickArea.pressed
@@ -634,9 +764,10 @@ ScrollView {
anchors.rightMargin: -width/2
width: 16 ; height: parent.height
anchors.right: parent.right
+ enabled: columnCount > 1
onPositionChanged: {
- var newHeaderWidth = columns[index].width + (mouseX - offset)
- columns[index].width = Math.max(minimumSize, newHeaderWidth)
+ var newHeaderWidth = modelData.width + (mouseX - offset)
+ modelData.width = Math.max(minimumSize, newHeaderWidth)
}
property bool found:false
@@ -651,21 +782,22 @@ ScrollView {
minWidth = Math.max(minWidth, item.children[1].children[index].children[0].implicitWidth)
}
if (minWidth)
- columns[index].width = minWidth
+ modelData.width = minWidth
}
onPressedChanged: if (pressed) offset=mouseX
- cursorShape: Qt.SplitHCursor
+ cursorShape: enabled ? Qt.SplitHCursor : Qt.ArrowCursor
}
}
}
}
Loader {
id: loader
- property string itemValue
- property string itemSort
- property bool itemPressed
- property bool itemContainsMouse
- property string itemPosition
+ property QtObject styleData: QtObject{
+ readonly property string value: ""
+ readonly property bool pressed: false
+ readonly property bool containsMouse: false
+ readonly property int column: -1
+ }
anchors.top: parent.top
anchors.right: parent.right