forked from qt-creator/qt-creator
		
	Change-Id: Ice592c6de9951ee3b2c4cb52ed0bb3b6770e0825 Reviewed-by: Eike Ziller <eike.ziller@digia.com>
		
			
				
	
	
		
			602 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			QML
		
	
	
	
	
	
			
		
		
	
	
			602 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			QML
		
	
	
	
	
	
| /****************************************************************************
 | |
| **
 | |
| ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 | |
| ** Contact: http://www.qt-project.org/legal
 | |
| **
 | |
| ** This file is part of Qt Creator.
 | |
| **
 | |
| ** 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 Digia.  For licensing terms and
 | |
| ** conditions see http://qt.digia.com/licensing.  For further information
 | |
| ** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional
 | |
| ** rights.  These rights are described in the Digia Qt LGPL Exception
 | |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | |
| **
 | |
| ****************************************************************************/
 | |
| 
 | |
| 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}
 | |
| }
 |