BasicTableView.qml 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2016 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and The Qt Company. For licensing terms
  14. ** and conditions see https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 3 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL3 included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 3 requirements
  23. ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  24. **
  25. ** GNU General Public License Usage
  26. ** Alternatively, this file may be used under the terms of the GNU
  27. ** General Public License version 2.0 or (at your option) the GNU General
  28. ** Public license version 3 or any later version approved by the KDE Free
  29. ** Qt Foundation. The licenses are as published by the Free Software
  30. ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  31. ** included in the packaging of this file. Please review the following
  32. ** information to ensure the GNU General Public License requirements will
  33. ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  34. ** https://www.gnu.org/licenses/gpl-3.0.html.
  35. **
  36. ** $QT_END_LICENSE$
  37. **
  38. ****************************************************************************/
  39. //
  40. // W A R N I N G
  41. // -------------
  42. //
  43. // This file is not part of the Qt API. It exists purely as an
  44. // implementation detail. This file may change from version to
  45. // version without notice, or even be removed.
  46. //
  47. // We mean it.
  48. //
  49. import QtQml 2.14 as Qml
  50. import QtQuick 2.6
  51. import QtQuick.Controls 1.5
  52. import QtQuick.Controls.Private 1.0
  53. import QtQuick.Controls.Styles 1.2
  54. import QtQuick.Window 2.2
  55. /*!
  56. \qmltype BasicTableView
  57. \qmlabstract
  58. \inqmlmodule QtQuick.Controls.Private
  59. */
  60. ScrollView {
  61. id: root
  62. /*! \qmlproperty bool BasicTableView::alternatingRowColors
  63. This property is set to \c true if the view alternates the row color.
  64. The default value is \c true.
  65. */
  66. property bool alternatingRowColors: true
  67. /*! \qmlproperty bool BasicTableView::headerVisible
  68. This property determines if the header is visible.
  69. The default value is \c true.
  70. */
  71. property bool headerVisible: true
  72. /*! \qmlproperty bool BasicTableView::backgroundVisible
  73. This property determines if the background should be filled or not.
  74. The default value is \c true.
  75. \note The rowDelegate is not affected by this property
  76. */
  77. property alias backgroundVisible: colorRect.visible
  78. /*! \qmlproperty Component BasicTableView::itemDelegate
  79. \internal
  80. Documentation differs between TableView and TreeView.
  81. See qtquickcontrols-treeview.qdoc and qtquickcontrols-tableview.qdoc
  82. */
  83. property Component itemDelegate: __style ? __style.itemDelegate : null
  84. /*! \qmlproperty Component BasicTableView::rowDelegate
  85. This property defines a delegate to draw a row.
  86. In the row delegate you have access to the following special properties:
  87. \list
  88. \li styleData.alternate - true when the row uses the alternate background color
  89. \li styleData.selected - true when the row is currently selected
  90. \li styleData.row - the index of the row
  91. \li styleData.hasActiveFocus - true when the row has focus (since QtQuick.Controls 1.3)
  92. \li styleData.pressed - true when the row is pressed (since QtQuick.Controls 1.3)
  93. \endlist
  94. \note For performance reasons, created delegates can be recycled
  95. across multiple table rows. This implies that when you make use of implicit
  96. properties such as \c styleData.row or \c model, these values can change
  97. after the delegate has been constructed. This means that you should not assume
  98. that content is fixed when \c Component.onCompleted is called, but instead rely on
  99. bindings to such properties.
  100. */
  101. property Component rowDelegate: __style ? __style.rowDelegate : null
  102. /*! \qmlproperty Component BasicTableView::headerDelegate
  103. This property defines a delegate to draw a header.
  104. In the header delegate you have access to the following special properties:
  105. \list
  106. \li styleData.value - the value or text for this item
  107. \li styleData.column - the index of the column
  108. \li styleData.pressed - true when the column is being pressed
  109. \li styleData.containsMouse - true when the column is under the mouse
  110. \li styleData.textAlignment - the horizontal text alignment of the column (since QtQuickControls 1.1)
  111. \endlist
  112. */
  113. property Component headerDelegate: __style ? __style.headerDelegate : null
  114. /*! \qmlproperty int BasicTableView::sortIndicatorColumn
  115. Index of the current sort column.
  116. The default value is \c {0}.
  117. */
  118. property int sortIndicatorColumn
  119. /*! \qmlproperty bool BasicTableView::sortIndicatorVisible
  120. This property shows or hides the sort indicator
  121. The default value is \c false.
  122. \note The view itself does not sort the data.
  123. */
  124. property bool sortIndicatorVisible: false
  125. /*! \qmlproperty enumeration BasicTableView::sortIndicatorOrder
  126. This sets the sorting order of the sort indicator
  127. The allowed values are:
  128. \list
  129. \li Qt.AscendingOrder - the default
  130. \li Qt.DescendingOrder
  131. \endlist
  132. */
  133. property int sortIndicatorOrder: Qt.AscendingOrder
  134. /*! \qmlproperty Component BasicTableView::contentHeader
  135. This is the content header of the view.
  136. */
  137. property alias contentHeader: listView.header
  138. /*! \qmlproperty Component BasicTableView::contentFooter
  139. This is the content footer of the view.
  140. */
  141. property alias contentFooter: listView.footer
  142. /*! \qmlproperty int BasicTableView::columnCount
  143. The current number of columns
  144. */
  145. readonly property alias columnCount: columnModel.count
  146. /*! \qmlpropertygroup BasicTableView::section
  147. \internal
  148. \qmlproperty string BasicTableView::section.property
  149. \qmlproperty enumeration BasicTableView::section.criteria
  150. \qmlproperty Component BasicTableView::section.delegate
  151. \qmlproperty enumeration BasicTableView::section.labelPositioning
  152. Moved to the qdoc files to keep the grouped property layout.
  153. See qtquickcontrols-treeview.qdoc and qtquickcontrols-tableview.qdoc
  154. */
  155. property alias section: listView.section
  156. /*!
  157. \qmlproperty enumeration BasicTableView::selectionMode
  158. \since QtQuick.Controls 1.1
  159. This enum indicates how the view responds to user selections:
  160. The possible modes are:
  161. \list
  162. \li SelectionMode.NoSelection - Items cannot be selected.
  163. \li SelectionMode.SingleSelection - When the user selects an item,
  164. any already-selected item becomes unselected, and the user cannot
  165. unselect the selected item. (Default)
  166. \li SelectionMode.MultiSelection - When the user selects an item in the usual way,
  167. the selection status of that item is toggled and the other items are left alone.
  168. \li SelectionMode.ExtendedSelection - When the user selects an item in the usual way,
  169. the selection is cleared and the new item selected. However, if the user presses the
  170. Ctrl key when clicking on an item, the clicked item gets toggled and all other items
  171. are left untouched. If the user presses the Shift key while clicking
  172. on an item, all items between the current item and the clicked item are selected or unselected,
  173. depending on the state of the clicked item. Multiple items can be selected by dragging the
  174. mouse over them.
  175. \li SelectionMode.ContiguousSelection - When the user selects an item in the usual way,
  176. the selection is cleared and the new item selected. However, if the user presses the Shift key while
  177. clicking on an item, all items between the current item and the clicked item are selected.
  178. \endlist
  179. */
  180. property int selectionMode: SelectionMode.SingleSelection
  181. /*!
  182. \qmlmethod TableViewColumn BasicTableView::addColumn(object column)
  183. Adds a \a column and returns the added column.
  184. The \a column argument can be an instance of TableViewColumn,
  185. or a Component. The component has to contain a TableViewColumn.
  186. Otherwise \c null is returned.
  187. */
  188. function addColumn(column) {
  189. return insertColumn(columnCount, column)
  190. }
  191. /*!
  192. \qmlmethod TableViewColumn BasicTableView::insertColumn(int index, object column)
  193. Inserts a \a column at the given \a index and returns the inserted column.
  194. The \a column argument can be an instance of TableViewColumn,
  195. or a Component. The component has to contain a TableViewColumn.
  196. Otherwise \c null is returned.
  197. */
  198. function insertColumn(index, column) {
  199. if (__isTreeView && index === 0 && columnCount > 0) {
  200. console.warn(__viewTypeName + "::insertColumn(): Can't replace column 0")
  201. return null
  202. }
  203. var object = column
  204. if (typeof column['createObject'] === 'function') {
  205. object = column.createObject(root)
  206. } else if (object.__view) {
  207. console.warn(__viewTypeName + "::insertColumn(): you cannot add a column to multiple views")
  208. return null
  209. }
  210. if (index >= 0 && index <= columnCount && object.accessibleRole === Accessible.ColumnHeader) {
  211. object.__view = root
  212. columnModel.insert(index, {columnItem: object})
  213. if (root.__columns[index] !== object) {
  214. // The new column needs to be put into __columns at the specified index
  215. // so the list needs to be recreated to be correct
  216. var arr = []
  217. for (var i = 0; i < index; ++i)
  218. arr.push(root.__columns[i])
  219. arr.push(object)
  220. for (i = index; i < root.__columns.length; ++i)
  221. arr.push(root.__columns[i])
  222. root.__columns = arr
  223. }
  224. return object
  225. }
  226. if (object !== column)
  227. object.destroy()
  228. console.warn(__viewTypeName + "::insertColumn(): invalid argument")
  229. return null
  230. }
  231. /*!
  232. \qmlmethod void BasicTableView::removeColumn(int index)
  233. Removes and destroys a column at the given \a index.
  234. */
  235. function removeColumn(index) {
  236. if (index < 0 || index >= columnCount) {
  237. console.warn(__viewTypeName + "::removeColumn(): invalid argument")
  238. return
  239. }
  240. if (__isTreeView && index === 0) {
  241. console.warn(__viewTypeName + "::removeColumn(): Can't remove column 0")
  242. return
  243. }
  244. var column = columnModel.get(index).columnItem
  245. columnModel.remove(index, 1)
  246. column.destroy()
  247. }
  248. /*!
  249. \qmlmethod void BasicTableView::moveColumn(int from, int to)
  250. Moves a column \a from index \a to another.
  251. */
  252. function moveColumn(from, to) {
  253. if (from < 0 || from >= columnCount || to < 0 || to >= columnCount) {
  254. console.warn(__viewTypeName + "::moveColumn(): invalid argument")
  255. return
  256. }
  257. if (__isTreeView && to === 0) {
  258. console.warn(__viewTypeName + "::moveColumn(): Can't move column 0")
  259. return
  260. }
  261. if (sortIndicatorColumn === from)
  262. sortIndicatorColumn = to
  263. columnModel.move(from, to, 1)
  264. }
  265. /*!
  266. \qmlmethod TableViewColumn BasicTableView::getColumn(int index)
  267. Returns the column at the given \a index
  268. or \c null if the \a index is invalid.
  269. */
  270. function getColumn(index) {
  271. if (index < 0 || index >= columnCount)
  272. return null
  273. return columnModel.get(index).columnItem
  274. }
  275. /*!
  276. \qmlmethod void BasicTableView::resizeColumnsToContents()
  277. Resizes all columns to ensure that the column contents and the headers will fit.
  278. \since QtQuick.Controls 1.2
  279. */
  280. function resizeColumnsToContents () {
  281. for (var i = 0; i < __columns.length; ++i) {
  282. var col = getColumn(i)
  283. var header = __listView.headerItem.headerRepeater.itemAt(i)
  284. if (col) {
  285. col.resizeToContents()
  286. if (col.width < header.implicitWidth)
  287. col.width = header.implicitWidth
  288. }
  289. }
  290. }
  291. // Internal stuff. Do not look
  292. Component.onCompleted: {
  293. for (var i = 0; i < __columns.length; ++i) {
  294. var column = __columns[i]
  295. if (column.accessibleRole === Accessible.ColumnHeader)
  296. addColumn(column)
  297. }
  298. }
  299. activeFocusOnTab: true
  300. implicitWidth: 200
  301. implicitHeight: 150
  302. frameVisible: true
  303. __scrollBarTopMargin: headerVisible && (listView.transientScrollBars || Qt.platform.os === "osx")
  304. ? listView.headerItem.height : 0
  305. /*! \internal
  306. Use this to display user-friendly messages in TableView and TreeView common functions.
  307. */
  308. property string __viewTypeName
  309. /*! \internal */
  310. readonly property bool __isTreeView: __viewTypeName === "TreeView"
  311. /*! \internal */
  312. default property alias __columns: root.data
  313. /*! \internal */
  314. property alias __currentRowItem: listView.currentItem
  315. /*! \internal
  316. This property is forwarded to TableView::currentRow, but not to any TreeView property.
  317. */
  318. property alias __currentRow: listView.currentIndex
  319. /*! \internal */
  320. readonly property alias __listView: listView
  321. /*! \internal */
  322. property Component __itemDelegateLoader: null
  323. /*! \internal
  324. Allows to override the model property in cases like TreeView,
  325. where we want to use a proxy/adaptor model between the user's model
  326. and whatever a ListView can swallow.
  327. */
  328. property var __model
  329. /*! \internal */
  330. property bool __activateItemOnSingleClick: __style ? __style.activateItemOnSingleClick : false
  331. /*! \internal */
  332. property Item __mouseArea
  333. ListView {
  334. id: listView
  335. focus: true
  336. activeFocusOnTab: false
  337. Keys.forwardTo: [__mouseArea]
  338. anchors.fill: parent
  339. contentWidth: headerItem.headerRow.width + listView.vScrollbarPadding
  340. // ### FIXME Late configuration of the header item requires
  341. // this binding to get the header visible after creation
  342. contentY: -headerItem.height
  343. currentIndex: -1
  344. visible: columnCount > 0
  345. interactive: Settings.hasTouchScreen
  346. property var rowItemStack: [] // Used as a cache for rowDelegates
  347. readonly property bool transientScrollBars: __style && !!__style.transientScrollBars
  348. readonly property real vScrollbarPadding: __scroller.verticalScrollBar.visible
  349. && !transientScrollBars && Qt.platform.os === "osx" ?
  350. __verticalScrollBar.width + __scroller.scrollBarSpacing + root.__style.padding.right : 0
  351. Qml.Binding {
  352. // On Mac, we reserve the vSB space in the contentItem because the vSB should
  353. // appear under the header. Unfortunately, the ListView header won't expand
  354. // beyond the ListView's boundaries, that's why we need to ressort to this.
  355. target: root.__scroller
  356. when: Qt.platform.os === "osx"
  357. property: "verticalScrollbarOffset"
  358. value: 0
  359. restoreMode: Binding.RestoreBinding
  360. }
  361. function incrementCurrentIndexBlocking() {
  362. var oldIndex = __listView.currentIndex
  363. __scroller.blockUpdates = true;
  364. incrementCurrentIndex();
  365. __scroller.blockUpdates = false;
  366. return oldIndex !== __listView.currentIndex
  367. }
  368. function decrementCurrentIndexBlocking() {
  369. var oldIndex = __listView.currentIndex
  370. __scroller.blockUpdates = true;
  371. decrementCurrentIndex();
  372. __scroller.blockUpdates = false;
  373. return oldIndex !== __listView.currentIndex
  374. }
  375. function scrollIfNeeded(key) {
  376. var diff = key === Qt.Key_PageDown ? height :
  377. key === Qt.Key_PageUp ? -height : 0
  378. if (diff !== 0)
  379. __verticalScrollBar.value += diff
  380. }
  381. SystemPalette {
  382. id: palette
  383. colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
  384. }
  385. Rectangle {
  386. id: colorRect
  387. parent: viewport
  388. anchors.fill: parent
  389. color: __style ? __style.backgroundColor : palette.base
  390. z: -2
  391. }
  392. // Fills extra rows with alternate color
  393. Column {
  394. id: rowfiller
  395. Loader {
  396. id: rowSizeItem
  397. sourceComponent: root.rowDelegate
  398. visible: false
  399. property QtObject styleData: QtObject {
  400. property bool alternate: false
  401. property bool selected: false
  402. property bool hasActiveFocus: false
  403. property bool pressed: false
  404. }
  405. }
  406. property int rowHeight: Math.floor(rowSizeItem.implicitHeight)
  407. property int paddedRowCount: rowHeight != 0 ? height/rowHeight : 0
  408. y: listView.contentHeight - listView.contentY + listView.originY
  409. width: parent.width
  410. visible: alternatingRowColors
  411. height: listView.model && listView.model.count ? (viewport.height - listView.contentHeight) : 0
  412. Repeater {
  413. model: visible ? parent.paddedRowCount : 0
  414. Loader {
  415. width: rowfiller.width
  416. height: rowfiller.rowHeight
  417. sourceComponent: root.rowDelegate
  418. property QtObject styleData: QtObject {
  419. readonly property bool alternate: (index + __listView.count) % 2 === 1
  420. readonly property bool selected: false
  421. readonly property bool hasActiveFocus: false
  422. readonly property bool pressed: false
  423. }
  424. readonly property var model: null
  425. readonly property var modelData: null
  426. }
  427. }
  428. }
  429. ListModel {
  430. id: columnModel
  431. }
  432. highlightFollowsCurrentItem: true
  433. model: root.__model
  434. delegate: FocusScope {
  435. id: rowItemContainer
  436. activeFocusOnTab: false
  437. z: rowItem.activeFocus ? 0.7 : rowItem.itemSelected ? 0.5 : 0
  438. property Item rowItem
  439. // We recycle instantiated row items to speed up list scrolling
  440. Component.onDestruction: {
  441. // move the rowItem back in cache
  442. if (rowItem) {
  443. rowItem.visible = false;
  444. rowItem.parent = null;
  445. rowItem.rowIndex = -1;
  446. listView.rowItemStack.push(rowItem); // return rowItem to cache
  447. }
  448. }
  449. Component.onCompleted: {
  450. // retrieve row item from cache
  451. if (listView.rowItemStack.length > 0)
  452. rowItem = listView.rowItemStack.pop();
  453. else
  454. rowItem = rowComponent.createObject(listView);
  455. // Bind container to item size
  456. rowItemContainer.width = Qt.binding( function() { return rowItem.width });
  457. rowItemContainer.height = Qt.binding( function() { return rowItem.height });
  458. // Reassign row-specific bindings
  459. rowItem.rowIndex = Qt.binding( function() { return model.index });
  460. rowItem.itemModelData = Qt.binding( function() { return typeof modelData === "undefined" ? null : modelData });
  461. rowItem.itemModel = Qt.binding( function() { return model });
  462. rowItem.parent = rowItemContainer;
  463. rowItem.visible = true;
  464. }
  465. }
  466. Component {
  467. id: rowComponent
  468. FocusScope {
  469. id: rowitem
  470. visible: false
  471. property int rowIndex
  472. property var itemModelData
  473. property var itemModel
  474. property bool itemSelected: __mouseArea.selected(rowIndex)
  475. property bool alternate: alternatingRowColors && rowIndex % 2 === 1
  476. readonly property color itemTextColor: itemSelected ? __style.highlightedTextColor : __style.textColor
  477. property Item branchDecoration: null
  478. width: itemrow.width
  479. height: rowstyle.height
  480. onActiveFocusChanged: {
  481. if (activeFocus)
  482. listView.currentIndex = rowIndex
  483. }
  484. Loader {
  485. id: rowstyle
  486. // row delegate
  487. sourceComponent: rowitem.itemModel !== undefined ? root.rowDelegate : null
  488. // Row fills the view width regardless of item size
  489. // But scrollbar should not adjust to it
  490. height: item ? item.height : 16
  491. width: parent.width + __horizontalScrollBar.width
  492. x: listView.contentX
  493. // these properties are exposed to the row delegate
  494. // Note: these properties should be mirrored in the row filler as well
  495. property QtObject styleData: QtObject {
  496. readonly property int row: rowitem.rowIndex
  497. readonly property bool alternate: rowitem.alternate
  498. readonly property bool selected: rowitem.itemSelected
  499. readonly property bool hasActiveFocus: rowitem.activeFocus
  500. readonly property bool pressed: rowitem.rowIndex === __mouseArea.pressedRow
  501. }
  502. readonly property var model: rowitem.itemModel
  503. readonly property var modelData: rowitem.itemModelData
  504. }
  505. Row {
  506. id: itemrow
  507. height: parent.height
  508. Repeater {
  509. model: columnModel
  510. delegate: __itemDelegateLoader
  511. onItemAdded: {
  512. var columnItem = columnModel.get(index).columnItem
  513. item.__rowItem = rowitem
  514. item.__column = columnItem
  515. }
  516. }
  517. }
  518. }
  519. }
  520. headerPositioning: ListView.OverlayHeader
  521. header: Item {
  522. id: tableHeader
  523. visible: headerVisible
  524. width: Math.max(headerRow.width + listView.vScrollbarPadding, root.viewport.width)
  525. height: visible ? headerRow.height : 0
  526. property alias headerRow: row
  527. property alias headerRepeater: repeater
  528. Row {
  529. id: row
  530. Repeater {
  531. id: repeater
  532. property int targetIndex: -1
  533. property int dragIndex: -1
  534. model: columnModel
  535. delegate: Item {
  536. id: headerRowDelegate
  537. readonly property int column: index
  538. z:-index
  539. width: modelData.width
  540. implicitWidth: columnCount === 1 ? viewport.width + __verticalScrollBar.width : headerStyle.implicitWidth
  541. visible: modelData.visible
  542. height: headerStyle.height
  543. readonly property bool treeViewMovable: !__isTreeView || index > 0
  544. Loader {
  545. id: headerStyle
  546. sourceComponent: root.headerDelegate
  547. width: parent.width
  548. property QtObject styleData: QtObject {
  549. readonly property string value: modelData.title
  550. readonly property bool pressed: headerClickArea.pressed
  551. readonly property bool containsMouse: headerClickArea.containsMouse
  552. readonly property int column: index
  553. readonly property int textAlignment: modelData.horizontalAlignment
  554. readonly property bool resizable: modelData.resizable
  555. }
  556. }
  557. Rectangle{
  558. id: targetmark
  559. width: parent.width
  560. height:parent.height
  561. opacity: (treeViewMovable && index === repeater.targetIndex && repeater.targetIndex !== repeater.dragIndex) ? 0.5 : 0
  562. Behavior on opacity { NumberAnimation { duration: 160 } }
  563. color: palette.highlight
  564. visible: modelData.movable
  565. }
  566. MouseArea{
  567. id: headerClickArea
  568. drag.axis: Qt.YAxis
  569. hoverEnabled: Settings.hoverEnabled
  570. anchors.fill: parent
  571. onClicked: {
  572. if (sortIndicatorColumn === index)
  573. sortIndicatorOrder = sortIndicatorOrder === Qt.AscendingOrder ? Qt.DescendingOrder : Qt.AscendingOrder
  574. sortIndicatorColumn = index
  575. }
  576. // Here we handle moving header sections
  577. // NOTE: the direction is different from the master branch
  578. // so this indicates that I am using an invalid assumption on item ordering
  579. onPositionChanged: {
  580. if (drag.active && modelData.movable && pressed && columnCount > 1) { // only do this while dragging
  581. for (var h = columnCount-1 ; h >= 0 ; --h) {
  582. if (headerRow.children[h].visible && drag.target.x + headerRowDelegate.width/2 > headerRow.children[h].x) {
  583. repeater.targetIndex = h
  584. break
  585. }
  586. }
  587. }
  588. }
  589. onPressed: {
  590. repeater.dragIndex = index
  591. }
  592. onReleased: {
  593. if (repeater.targetIndex >= 0 && repeater.targetIndex !== index ) {
  594. var targetColumn = columnModel.get(repeater.targetIndex).columnItem
  595. if (targetColumn.movable && (!__isTreeView || repeater.targetIndex > 0)) {
  596. if (sortIndicatorColumn === index)
  597. sortIndicatorColumn = repeater.targetIndex
  598. columnModel.move(index, repeater.targetIndex, 1)
  599. }
  600. }
  601. repeater.targetIndex = -1
  602. repeater.dragIndex = -1
  603. }
  604. drag.target: treeViewMovable && modelData.movable && columnCount > 1 ? draghandle : null
  605. }
  606. Loader {
  607. id: draghandle
  608. property QtObject styleData: QtObject{
  609. readonly property string value: modelData.title
  610. readonly property bool pressed: headerClickArea.pressed
  611. readonly property bool containsMouse: headerClickArea.containsMouse
  612. readonly property int column: index
  613. readonly property int textAlignment: modelData.horizontalAlignment
  614. }
  615. parent: tableHeader
  616. x: __implicitX
  617. property double __implicitX: headerRowDelegate.x
  618. width: modelData.width
  619. height: parent.height
  620. sourceComponent: root.headerDelegate
  621. visible: headerClickArea.pressed
  622. onVisibleChanged: {
  623. if (!visible)
  624. x = Qt.binding(function () { return __implicitX })
  625. }
  626. opacity: 0.5
  627. }
  628. MouseArea {
  629. id: headerResizeHandle
  630. property int offset: 0
  631. readonly property int minimumSize: 20
  632. preventStealing: true
  633. anchors.rightMargin: -width/2
  634. width: Settings.hasTouchScreen ? Screen.pixelDensity * 3.5 : 16
  635. height: parent.height
  636. anchors.right: parent.right
  637. enabled: modelData.resizable && columnCount > 0
  638. onPositionChanged: {
  639. var newHeaderWidth = modelData.width + (mouseX - offset)
  640. modelData.width = Math.max(minimumSize, newHeaderWidth)
  641. }
  642. onDoubleClicked: getColumn(index).resizeToContents()
  643. onPressedChanged: if (pressed) offset=mouseX
  644. cursorShape: enabled && repeater.dragIndex==-1 ? Qt.SplitHCursor : Qt.ArrowCursor
  645. }
  646. }
  647. }
  648. }
  649. Loader {
  650. property QtObject styleData: QtObject{
  651. readonly property string value: ""
  652. readonly property bool pressed: false
  653. readonly property bool containsMouse: false
  654. readonly property int column: -1
  655. readonly property int textAlignment: Text.AlignLeft
  656. }
  657. anchors.top: parent.top
  658. anchors.right: parent.right
  659. anchors.bottom: headerRow.bottom
  660. sourceComponent: root.headerDelegate
  661. readonly property real __remainingWidth: parent.width - headerRow.width
  662. visible: __remainingWidth > 0
  663. width: __remainingWidth
  664. z:-1
  665. }
  666. }
  667. function columnAt(offset) {
  668. var item = listView.headerItem.headerRow.childAt(offset, 0)
  669. return item ? item.column : -1
  670. }
  671. }
  672. }