diff options
author | Daniel Molkentin <daniel.molkentin@nokia.com> | 2011-08-02 17:11:29 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@nokia.com> | 2011-08-03 16:12:35 +0200 |
commit | 9743b43663f2dac99df0e1e5219b0d65bee2d7f2 (patch) | |
tree | a41f3e18eaae73aac5cebc7150f7aed5662974e9 /lib/qtcreator/qtcomponents/TableView.qml | |
parent | 6c8edcf99ed0cd77a3667e61417a224461060ab7 (diff) |
Make Components installable. Fix Shadow Build.
Task-Number: QTCREATORBUG-5672
Done-with: Oswald Buddenhagen
Change-Id: I61f8a83205bc338ba12e43b7471eaa957da2b004
Reviewed-on: http://codereview.qt.nokia.com/2451
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
Diffstat (limited to 'lib/qtcreator/qtcomponents/TableView.qml')
-rw-r--r-- | lib/qtcreator/qtcomponents/TableView.qml | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/lib/qtcreator/qtcomponents/TableView.qml b/lib/qtcreator/qtcomponents/TableView.qml new file mode 100644 index 0000000000..132610c3f6 --- /dev/null +++ b/lib/qtcreator/qtcomponents/TableView.qml @@ -0,0 +1,604 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +import QtQuick 1.0 + +/* +* +* TableView +* +* This component provides an item-view with resizable +* header sections. +* +* You can style the drawn delegate by overriding the itemDelegate +* property. The following properties are supported for custom +* delegates: +* +* Note: Currently only row selection is available for this component +* +* itemheight - default platform size of item +* itemwidth - default platform width of item +* itemselected - if the row is currently selected +* itemvalue - The text for this item +* itemforeground - The default text color for an item +* +* For example: +* itemDelegate: Item { +* Text { +* anchors.verticalCenter: parent.verticalCenter +* color: itemForeground +* elide: Text.ElideRight +* text: itemValue +* } +* } +* +* Data for each row is provided through a model: +* +* ListModel { +* ListElement{ column1: "value 1"; column2: "value 2"} +* ListElement{ column1: "value 3"; column2: "value 4"} +* } +* +* You provide title and size properties on TableColumns +* by setting the default header property : +* +* TableView { +* TableColumn{ property: "column1" ; caption: "Column 1" ; width:100} +* TableColumn{ property: "column2" ; caption: "Column 2" ; width:200} +* model: datamodel +* } +* +* The header sections are attached to values in the datamodel by defining +* the listmodel property they attach to. Each property in the model, will +* then be shown in each column section. +* +* The view itself does not provide sorting. This has to +* be done on the model itself. However you can provide sorting +* on the model and enable sort indicators on headers. +* +* sortColumn - The index of the currently selected sort header +* sortIndicatorVisible - If sort indicators should be enabled +* sortIndicatorDirection - "up" or "down" depending on state +* +*/ + +FocusScope{ + id: root + property variant model + property int frameWidth: frame ? styleitem.pixelMetric("defaultframewidth") : 0; + property alias contentHeight : tree.contentHeight + property alias contentWidth: tree.contentWidth + property bool frame: true + property bool highlightOnFocus: false + property bool frameAroundContents: styleitem.styleHint("framearoundcontents") + property int sortColumn // Index of currently selected sort column + + property bool sortIndicatorVisible: false // enables or disables sort indicator + property string sortIndicatorDirection: "down" // "up" or "down" depending on current state + + property bool alternateRowColor: true + property alias contentX: tree.contentX + property alias contentY: tree.contentY + + property alias currentIndex: tree.currentIndex // Should this be currentRowIndex? + + property int headerHeight: headerrow.height + + property Component itemDelegate: standardDelegate + property Component rowDelegate: rowDelegate + property Component headerDelegate: headerDelegate + property alias cacheBuffer: tree.cacheBuffer + + property bool headerVisible: true + + default property alias header: tree.header + + signal activated + + Component { + id: standardDelegate + Item { + property int implicitWidth: sizehint.paintedWidth + 4 + Text { + width: parent.width + anchors.margins: 4 + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + elide: itemElideMode + text: itemValue ? itemValue : "" + color: itemForeground + } + Text { + id: sizehint + text: itemValue ? itemValue : "" + visible:false + } + } + } + + Component { + id: nativeDelegate + // This gives more native styling, but might be less performant + QStyleItem { + elementType: "item" + text: itemValue + selected: itemSelected + } + } + + Component { + id: headerDelegate + QStyleItem { + elementType: "header" + activeControl: itemSort + raised: true + sunken: itemPressed + text: itemValue + hover: itemContainsMouse + } + } + + Component { + id: rowDelegate + QStyleItem { + id: rowstyle + elementType: "itemrow" + activeControl: itemAlternateBackground ? "alternate" : "" + selected: itemSelected ? "true" : "false" + } + } + + Rectangle { + id: colorRect + color: "white" + anchors.fill: frameitem + anchors.margins: frameWidth + anchors.rightMargin: (!frameAroundContents && vscrollbar.visible ? vscrollbar.width : 0) + frameWidth + anchors.bottomMargin: (!frameAroundContents && hscrollbar.visible ? hscrollbar.height : 0) +frameWidth + } + + QStyleItem { + id: frameitem + elementType: "frame" + onElementTypeChanged: scrollarea.frameWidth = styleitem.pixelMetric("defaultframewidth"); + sunken: true + visible: frame + anchors.fill: parent + anchors.rightMargin: frame ? (frameAroundContents ? (vscrollbar.visible ? vscrollbar.width + 2 * frameMargins : 0) : -frameWidth) : 0 + anchors.bottomMargin: frame ? (frameAroundContents ? (hscrollbar.visible ? hscrollbar.height + 2 * frameMargins : 0) : -frameWidth) : 0 + anchors.topMargin: frame ? (frameAroundContents ? 0 : -frameWidth) : 0 + property int scrollbarspacing: styleitem.pixelMetric("scrollbarspacing"); + property int frameMargins : frame ? scrollbarspacing : 0 + } + MouseArea { + id: mousearea + + anchors.fill: tree + + property bool autoincrement: false + property bool autodecrement: false + + onReleased: { + autoincrement = false + autodecrement = false + } + + // Handle vertical scrolling whem dragging mouse outside boundraries + + Timer { running: mousearea.autoincrement; repeat: true; interval: 30 ; onTriggered: tree.incrementCurrentIndex()} + Timer { running: mousearea.autodecrement; repeat: true; interval: 30 ; onTriggered: tree.decrementCurrentIndex()} + + onMousePositionChanged: { + if (mouseY > tree.height) { + autodecrement = false + autoincrement = true + } else if (mouseY < 0) { + autoincrement = false + autodecrement = true + } else { + autoincrement = false + autodecrement = false + } + + var y = Math.min(contentY + tree.height - 5, Math.max(mouseY + contentY, contentY)) + + var newIndex = tree.indexAt(0, y) + if (newIndex > 0) + tree.currentIndex = tree.indexAt(0, y) + } + onPressed: { + tree.forceActiveFocus() + var x = Math.min(contentWidth - 5, Math.max(mouseX + contentX, 0)) + var y = Math.min(contentHeight - 5, Math.max(mouseY + contentY, 0)) + tree.currentIndex = tree.indexAt(x, y) + } + + onDoubleClicked: { + parent.activated() + } + } + + ListView { + id: tree + property list<TableColumn> header + property bool blockUpdates: false + highlightFollowsCurrentItem: true + model: root.model + + interactive: false + anchors.top: tableColumn.bottom + anchors.topMargin: -frameWidth + anchors.left: frameitem.left + anchors.right: frameitem.right + anchors.bottom: frameitem.bottom + anchors.margins: frameWidth + + anchors.rightMargin: (!frameAroundContents && vscrollbar.visible ? vscrollbar.width: 0) + frameWidth + anchors.bottomMargin: (!frameAroundContents && hscrollbar.visible ? hscrollbar.height : 0) + frameWidth + + focus: true + clip: true + + Keys.onUpPressed: { + blockUpdates = true + if (currentIndex > 0) currentIndex = currentIndex - 1 + wheelarea.verticalValue = contentY/wheelarea.scale + blockUpdates = false + } + Keys.onDownPressed: { + blockUpdates = true + if (currentIndex< count - 1) currentIndex = currentIndex + 1 + wheelarea.verticalValue = contentY/wheelarea.scale + blockUpdates = false + } + Keys.onPressed: { + if (event.key == Qt.Key_PageUp) { + vscrollbar.value = vscrollbar.value - tree.height + } else if (event.key == Qt.Key_PageDown) + vscrollbar.value = vscrollbar.value + tree.height + } + + onContentYChanged: { + // positionViewAtIndex(currentIndex, ListView.Visible) + // highlight follows item + blockUpdates = true + vscrollbar.value = tree.contentY + blockUpdates = false + } + + delegate: Item { + id: rowitem + width: row.width + height: row.height + anchors.margins: frameWidth + property int rowIndex: model.index + property bool itemAlternateBackground: alternateRowColor && rowIndex % 2 == 1 + Loader { + id: rowstyle + // row delegate + sourceComponent: root.rowDelegate + // Row fills the tree width regardless of item size + // But scrollbar should not adjust to it + width: frameitem.width + height: row.height + x: contentX + + property bool itemAlternateBackground: rowitem.itemAlternateBackground + property bool itemSelected: rowitem.ListView.isCurrentItem + } + Row { + id: row + anchors.left: parent.left + + Repeater { + id: repeater + model: root.header.length + Loader { + id: itemDelegateLoader + visible: header[index].visible + sourceComponent: itemDelegate + property variant model: tree.model + property variant itemProperty: header[index].property + + width: header[index].width + height: item ? item.height : Math.max(16, styleitem.sizeFromContents(16, 16).height) + + function getValue() { + if (index < header.length && + root.model.get(rowIndex).hasOwnProperty(header[index].property)) + return root.model.get(rowIndex)[ header[index].property] + } + property variant itemValue: root.model.get(rowIndex)[ header[index].property] + property bool itemSelected: rowitem.ListView.isCurrentItem + property color itemForeground: itemSelected ? rowstyleitem.highlightedTextColor : rowstyleitem.textColor + property int rowIndex: rowitem.rowIndex + property int columnIndex: index + property int itemElideMode: header[index].elideMode + } + } + onWidthChanged: tree.contentWidth = width + } + } + } + Text{ id:text } + + Item { + id: tableColumn + clip: true + anchors.top: frameitem.top + anchors.left: frameitem.left + anchors.right: frameitem.right + anchors.margins: frameWidth + visible: headerVisible + Behavior on height { NumberAnimation{duration:80}} + height: headerVisible ? styleitem.sizeFromContents(text.font.pixelSize, styleitem.fontHeight).height : frameWidth + + Row { + id: headerrow + + anchors.top: parent.top + height:parent.height + x: -tree.contentX + + Repeater { + id: repeater + model: header.length + property int targetIndex: -1 + property int dragIndex: -1 + delegate: Item { + z:-index + width: header[index].width + visible: header[index].visible + height: headerrow.height + + Loader { + sourceComponent: root.headerDelegate + anchors.fill: parent + property string itemValue: header[index].caption + property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : ""; + property bool itemPressed: headerClickArea.pressed + property bool itemContainsMouse: headerClickArea.containsMouse + } + Rectangle{ + id: targetmark + width: parent.width + height:parent.height + opacity: (index == repeater.targetIndex && repeater.targetIndex != repeater.dragIndex) ? 0.5 : 0 + Behavior on opacity { NumberAnimation{duration:160}} + color: palette.highlight + } + + MouseArea{ + id: headerClickArea + drag.axis: Qt.YAxis + hoverEnabled: true + anchors.fill: parent + onClicked: { + if (sortColumn == index) + sortIndicatorDirection = sortIndicatorDirection === "up" ? "down" : "up" + sortColumn = index + } + // Here we handle moving header sections + onMousePositionChanged: { + if (pressed) { // only do this while dragging + for (var h = 0 ; h < header.length ; ++h) { + if (drag.target.x > headerrow.children[h].x - 10) { + repeater.targetIndex = header.length - h - 1 + break + } + } + } + } + + onPressed: { + repeater.dragIndex = index + draghandle.x = parent.x + } + + onReleased: { + if (repeater.targetIndex >= 0 && repeater.targetIndex != index ) { + // Rearrange the header sections + var items = new Array + for (var i = 0 ; i< header.length ; ++i) + items.push(header[i]) + items.splice(index, 1); + items.splice(repeater.targetIndex, 0, header[index]); + header = items + if (sortColumn == index) + sortColumn = repeater.targetIndex + } + repeater.targetIndex = -1 + } + drag.maximumX: 1000 + drag.minimumX: -1000 + drag.target: draghandle + } + + Loader { + id: draghandle + parent: tableColumn + sourceComponent: root.headerDelegate + width: header[index].width + height: parent.height + property string itemValue: header[index].caption + property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : ""; + property bool itemPressed: headerClickArea.pressed + property bool itemContainsMouse: headerClickArea.containsMouse + visible: headerClickArea.pressed + opacity: 0.5 + } + + + MouseArea { + id: headerResizeHandle + property int offset: 0 + property int minimumSize: 20 + anchors.rightMargin: -width/2 + width: 16 ; height: parent.height + anchors.right: parent.right + onPositionChanged: { + var newHeaderWidth = header[index].width + (mouseX - offset) + header[index].width = Math.max(minimumSize, newHeaderWidth) + } + property bool found:false + + onDoubleClicked: { + var row + var minWidth = 0 + var listdata = tree.children[0] + for (row = 0 ; row < listdata.children.length ; ++row){ + var item = listdata.children[row+1] + if (item && item.children[1] && item.children[1].children[index] && + item.children[1].children[index].children[0].hasOwnProperty("implicitWidth")) + minWidth = Math.max(minWidth, item.children[1].children[index].children[0].implicitWidth) + } + if (minWidth) + header[index].width = minWidth + } + onPressedChanged: if(pressed)offset=mouseX + QStyleItem { + anchors.fill: parent + cursor: "splithcursor" + } + } + } + } + } + Loader { + id: loader + z:-1 + sourceComponent: root.headerDelegate + anchors.top: parent.top + anchors.right: parent.right + anchors.bottom: headerrow.bottom + anchors.rightMargin: -2 + width: root.width - headerrow.width + property string itemValue + property string itemSort + property bool itemPressed + property bool itemContainsMouse + } + } + + WheelArea { + id: wheelarea + anchors.fill: parent + property int scale: 5 + horizontalMinimumValue: hscrollbar.minimumValue/scale + horizontalMaximumValue: hscrollbar.maximumValue/scale + verticalMinimumValue: vscrollbar.minimumValue/scale + verticalMaximumValue: vscrollbar.maximumValue/scale + + verticalValue: contentY/scale + horizontalValue: contentX/scale + + onVerticalValueChanged: { + if(!tree.blockUpdates) { + contentY = verticalValue * scale + vscrollbar.value = contentY + } + } + + onHorizontalValueChanged: { + if(!tree.blockUpdates) { + contentX = horizontalValue * scale + hscrollbar.value = contentX + } + } + } + + ScrollBar { + id: hscrollbar + orientation: Qt.Horizontal + property int availableWidth: root.width - vscrollbar.width + visible: contentWidth > availableWidth + maximumValue: contentWidth > availableWidth ? tree.contentWidth - availableWidth : 0 + minimumValue: 0 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: frameWidth + anchors.bottomMargin: styleitem.frameoffset + anchors.rightMargin: vscrollbar.visible ? scrollbarExtent : (frame ? 1 : 0) + onValueChanged: { + if (!tree.blockUpdates) + contentX = value + } + property int scrollbarExtent : styleitem.pixelMetric("scrollbarExtent"); + } + + ScrollBar { + id: vscrollbar + orientation: Qt.Vertical + // We cannot bind directly to tree.height due to binding loops so we have to redo the calculation here + property int availableHeight : root.height - (hscrollbar.visible ? hscrollbar.height : 0) - tableColumn.height + visible: contentHeight > availableHeight + maximumValue: contentHeight > availableHeight ? tree.contentHeight - availableHeight : 0 + minimumValue: 0 + anchors.rightMargin: styleitem.frameoffset + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.topMargin: styleitem.style == "mac" ? tableColumn.height : 0 + onValueChanged: { + if(!tree.blockUpdates) + contentY = value + } + anchors.bottomMargin: hscrollbar.visible ? hscrollbar.height : styleitem.frameoffset + + Keys.onUpPressed: if (tree.currentIndex > 0) tree.currentIndex = tree.currentIndex - 1 + Keys.onDownPressed: if (tree.currentIndex< tree.count - 1) tree.currentIndex = tree.currentIndex + 1 + } + + QStyleItem { + z: 2 + anchors.fill: parent + anchors.margins: -4 + visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget") + elementType: "focusframe" + } + + QStyleItem { + id: styleitem + elementType: "header" + visible:false + property int frameoffset: style === "mac" ? -1 : 0 + } + QStyleItem { + id: rowstyleitem + elementType: "item" + visible:false + property color textColor: styleHint("textColor") + property color highlightedTextColor: styleHint("highlightedTextColor") + } + SystemPalette{id:palette} +} |