Warning, /maui/mauikit/src/controls.6/ListBrowser.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *   Copyright 2018 Camilo Higuita <milo.h@aol.com>
0003  *
0004  *   This program is free software; you can redistribute it and/or modify
0005  *   it under the terms of the GNU Library General Public License as
0006  *   published by the Free Software Foundation; either version 2, or
0007  *   (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *   GNU General Public License for more details
0013  *
0014  *   You should have received a copy of the GNU Library General Public
0015  *   License along with this program; if not, write to the
0016  *   Free Software Foundation, Inc.,
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0018  */
0019 
0020 import QtQuick
0021 import QtQuick.Controls
0022 
0023 import org.mauikit.controls 1.3 as Maui
0024 
0025 /**
0026  * @inherit QtQuick.Item
0027  *  @brief A browser view with a list layout.
0028  *  <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-item.html">This controls inherits from QQC2 Item, to checkout its inherited properties refer to the Qt Docs.</a>
0029  *    
0030  * This component might seem similar to QQC2 ListView - and it does uses it underneath - but this one includes a few more predefined elements, such as a placeholder element, pinch to zoom gestures, lasso selection support, and some predefined behaviour. 
0031  *    
0032  * @section structure Structure
0033  * The browser has a dedicated placeholder element handled by MauiKit Holder, where a message can be set when the view is on a determined state the user should be warned about, such as if the view is empty, or not search results were found.
0034  * @see Holder
0035  * 
0036  * The lasso selection feature works with a mouse or a track-pad, and allows to select multiple items in the browser-view that are under the lasso rectangle area. A signal is emitted when the selection has been triggered - this is when the lasso rectangle is released - sending as an argument an array of numbers representing the indexes of the selected items.
0037  * @see itemsSelected 
0038  * 
0039  * @note Consider using as the delegate elements the MauiKit ListBrowserDelegate.
0040  * 
0041  * To position the delegates you can use the ListView attached properties, such as `ListView.view.width` to set the width of the delegate correctly.
0042  * 
0043  * @image html Browsers/listbrowser.png
0044  * 
0045  * @code
0046  * Maui.ListBrowser
0047  * {
0048  *    anchors.fill: parent
0049  *    model: 60
0050  * 
0051  *    enableLassoSelection: true
0052  *    onItemsSelected: (indexes) => console.log(indexes)
0053  * 
0054  *    delegate: Maui.ListBrowserDelegate
0055  *    {
0056  *        width: ListView.view.width
0057  *        label1.text: "An example delegate."
0058  *        label2.text: "Using the MauiKit ListBrowser."
0059  * 
0060  *        iconSource: "folder"
0061  *    }
0062  * }
0063  * @endcode
0064  * 
0065  * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/ListBrowser.qml">You can find a more complete example at this link.</a>
0066  */
0067 Item
0068 {
0069     id: control
0070     focus: true
0071     clip: false
0072     
0073     implicitHeight: contentHeight + topPadding + bottomPadding
0074     implicitWidth: contentWidth + leftPadding + rightPadding
0075     
0076     /**
0077      * @brief The model to be used to populate the browsing view.
0078      * @property var ListBrowser::model
0079      */
0080     property alias model : _listView.model
0081     
0082     /**
0083      * @brief The component to be used as the delegate.
0084      * @note Consider using the MauiKit delegate controls, such as ListBrowserDelegate, ListDelegate or LabelDelegate.
0085      * @property Component ListBrowser::delegate
0086      */
0087     property alias delegate : _listView.delegate
0088     
0089     /**
0090      * @brief The section group property to set the ListView sections.
0091      * Refer to the Qt documentation on the ListView section.
0092      * @property section ListBrowser::section
0093      */
0094     property alias section : _listView.section
0095     
0096     /**
0097      * @brief The position of the view contents on the Y axis.
0098      * @property double ListBrowser::contentY
0099      */
0100     property alias contentY: _listView.contentY
0101     
0102     /**
0103      * @brief The position of the view contents on the X axis.
0104      * @property double ListBrowser::contentY
0105      */
0106     property alias contentX: _listView.contentX
0107         
0108     /**
0109      * @brief The index number of the current element selected.
0110      * @note To no break any binding, use the `setCurrentIndex` function.
0111      * @property int ListBrowser::currentIndex
0112      */
0113     property alias currentIndex : _listView.currentIndex
0114     
0115     /**
0116      * @brief The current item selected.
0117      * @property Item ListBrowser::currentItem
0118      */
0119     property alias currentItem : _listView.currentItem
0120     
0121     /**
0122      * @brief The total amount of elements listed in the view.
0123      * @property int ListBrowser::count
0124      */
0125     property alias count : _listView.count
0126     
0127     /**
0128      * @brief The cache buffer. 
0129      * Refer to the QQC2 ListView for proper documentation.
0130      * @property int ListBrowser::cacheBuffer
0131      */
0132     property alias cacheBuffer : _listView.cacheBuffer
0133     
0134     /**
0135      * @brief The orientation of the list view.
0136      * By default this is set to `ListView.Vertical`.
0137      * @property enum ListBrowser::orientation
0138      */
0139     property alias orientation: _listView.orientation
0140     
0141     /**
0142      * @brief How to snap the elements of the list view while scrolling.
0143      * @note See Qt documentation.
0144      * @property enum ListBrowser::snapMode
0145      */
0146     property alias snapMode: _listView.snapMode
0147     
0148     /**
0149      * @brief The spacing between the elements in the list view.
0150      * By default this is set to `Style.defaultSpacing`
0151      * @property int ListBrowser::spacing
0152      */
0153     property alias spacing: _listView.spacing
0154     
0155     /**
0156      * @brief An alias to access the QQC2 ListView.
0157      * @property ListView ListBrowser::flickable
0158      */
0159     readonly property alias flickable : _listView
0160     
0161     /**
0162      * @brief An alias to access the QQC2 ScrollView.
0163      * @property ScrollView ListBrowser::scrollView
0164      */
0165     readonly property alias scrollView : _scrollView
0166     
0167     /**
0168      * @brief The total height of all the elements listed in the view.
0169      * @property int ListBrowser::contentHeight
0170      */
0171     property alias contentHeight : _listView.contentHeight
0172     
0173     /**
0174      * @brief The total width of all the elements.
0175      * @property int ListBrowser::contentWidth 
0176      */
0177     property alias contentWidth : _listView.contentWidth
0178     
0179     /**
0180      * @brief Whether the view is positioned at the end on the Y axis. 
0181      * Meant to be used if the view `orientation` has been set to vertical.
0182      * @property bool ListBrowser::atYEnd
0183      */
0184     readonly property alias atYEnd : _listView.atYEnd
0185     
0186     /**
0187      * @brief Whether the view is positioned at the beginning on the Y axis.
0188     * Meant to be used if the view `orientation` has been set to vertical.
0189      * @property bool ListBrowser::atYBeginning
0190      */
0191     readonly property alias atYBeginning : _listView.atYBeginning
0192     
0193     /**
0194      * @brief The top padding.
0195      * @see padding
0196      * @property int ListBrowser::topPadding
0197      */
0198     property alias topPadding: _scrollView.topPadding
0199     
0200    /**
0201      * @brief The bottom padding.
0202      * @see padding
0203      * @property int ListBrowser::bottomPadding
0204      */
0205     property alias bottomPadding: _scrollView.bottomPadding
0206     
0207     /**
0208      * @brief The right padding.
0209      * @see padding
0210      * @property int ListBrowser::rightPadding
0211      */
0212     property alias rightPadding: _scrollView.rightPadding
0213     
0214     /**
0215      * @brief The left padding.
0216      * @see padding
0217      * @property int ListBrowser::leftPadding
0218      */
0219     property alias leftPadding: _scrollView.leftPadding
0220     
0221     /**
0222      * @brief The total padding all around the list view. The padding is added to the ScrollView.
0223      * This is the same as setting `scrollView.padding`.
0224      * @property int ListBrowser::padding
0225      */
0226     property alias padding: _scrollView.padding
0227     
0228     /**
0229      * @brief The policy of the vertical scroll bar from the scroll view.
0230      * @see scrollView
0231      * The default value of this is picked based on the Style property `Style.scrollBarPolicy`, unless the orientation of the view is set to horizontal, in which case this is set to 'ScrollBar.AlwaysOff`.
0232      * Possible values are:
0233      * - ScrollBar.AlwaysOff
0234      * - ScrollBar.AlwaysOn
0235      * - ScrollBar.AsNeeded
0236      */
0237     property int verticalScrollBarPolicy:
0238     {
0239         if(control.orientation === ListView.Horizontal)
0240             return ScrollBar.AlwaysOff
0241             
0242             switch(Maui.Style.scrollBarPolicy)
0243             {
0244                 case Maui.Style.AlwaysOn: return ScrollBar.AlwaysOn;
0245                 case Maui.Style.AlwaysOff: return ScrollBar.AlwaysOff;
0246                 case Maui.Style.AsNeeded: return ScrollBar.AsNeeded;
0247                 case Maui.Style.AutoHide: return ScrollBar.AsNeeded;
0248             }
0249     }
0250     
0251     /**
0252      * @brief The policy of the horizontal scroll bar from the scroll view.
0253      * @see scrollView
0254      * The default value of this is picked based on the Style property `Style.scrollBarPolicy`, unless the orientation of the view is set to vertical, in which case this is set to 'ScrollBar.AlwaysOff`.
0255      * Possible values are:
0256      * - ScrollBar.AlwaysOff
0257      * - ScrollBar.AlwaysOn
0258      * - ScrollBar.AsNeeded
0259      */
0260     property int horizontalScrollBarPolicy:
0261     {
0262         if(control.orientation === ListView.Vertical)
0263             return ScrollBar.AlwaysOff
0264             
0265             switch(Maui.Style.scrollBarPolicy)
0266             {
0267                 case Maui.Style.AlwaysOn: return ScrollBar.AlwaysOn;
0268                 case Maui.Style.AlwaysOff: return ScrollBar.AlwaysOff;
0269                 case Maui.Style.AsNeeded: return ScrollBar.AsNeeded;
0270                 case Maui.Style.AutoHide: return ScrollBar.AsNeeded;
0271             }
0272     }
0273     
0274     /**
0275      * @brief An alias to access the placeholder properties. This is handled by a MauiKit Holder.
0276      * @see Holder::title
0277      * @see Holder::body
0278      * 
0279      * @property Holder ListBrowser::holder
0280      */
0281     property alias holder : _holder
0282     
0283     /**
0284      * @brief Whether to enable the lasso selection, to select multiple items.
0285      * By default this is set to `false`.
0286      * @see itemsSelected
0287      */
0288     property bool enableLassoSelection : false
0289     
0290     /**
0291      * @brief
0292      */
0293     property bool selectionMode: false
0294        
0295     /**
0296      * @brief An alias to the lasso rectangle.
0297      * @property Rectangle ListBrowser::lassoRec
0298      */
0299     readonly property alias lassoRec : selectLayer
0300     
0301     /**
0302      * @brief The header section of the ListView element.
0303      * @see flickable
0304      * @property Component ListBrowser::header
0305      */
0306     property alias header : _listView.header
0307     
0308     /**
0309      * @brief The footer section of the ListView element
0310      * @see flickable
0311      * @property Component ListBrowser::footer
0312      */
0313     property alias footer : _listView.footer
0314     
0315     /**
0316      * @brief The actual width of the view-port. This is the actual width without any padding.
0317      * @property int ListBrowser::availableWidth
0318      */
0319     readonly property alias availableWidth: _listView.width
0320     
0321     /**
0322      * @brief The actual height of the view-port. This is the actual height without any padding.
0323      * @property int ListBrowser::availableHeight
0324      */
0325     readonly property alias availableHeight: _listView.height
0326     
0327     /**
0328      * @brief Emitted when the lasso selection has been released.
0329      * @param indexes A array of index numbers is sent as the argument, representing the index value of the items under the lasso rectangle area.
0330      */
0331     signal itemsSelected(var indexes)
0332     
0333      /**
0334      * @brief Emitted when an empty space of the background area has been clicked.
0335      * @param mouse Object with information about the click event.
0336      */
0337     signal areaClicked(var mouse)
0338     
0339     /**
0340      * @brief Emitted when an empty space of the area area background has been right clicked.
0341      */
0342     signal areaRightClicked()
0343     
0344     /**
0345      * @brief Emitted when a physical key from the device has been pressed.
0346      * @param event The object with information about the event.
0347      */
0348     signal keyPress(var event)
0349     
0350     Keys.enabled : true
0351     Keys.forwardTo : _listView
0352     
0353     ScrollView
0354     {
0355         id: _scrollView
0356         anchors.fill: parent
0357         clip: control.clip
0358         focus: true
0359         padding: Maui.Style.contentMargins
0360         orientation: _listView.orientation
0361         
0362         ScrollBar.horizontal.policy: control.horizontalScrollBarPolicy
0363         ScrollBar.vertical.policy: control.verticalScrollBarPolicy
0364         
0365         contentHeight: _listView.contentHeight
0366         contentWidth: availableWidth
0367         
0368         ListView
0369         {
0370             id: _listView
0371             focus: true
0372             clip: control.clip
0373             
0374             property var selectedIndexes : []
0375             
0376             
0377             spacing: Maui.Style.defaultSpacing
0378             
0379             snapMode: ListView.NoSnap
0380             
0381             displayMarginBeginning: Maui.Style.toolBarHeight * 4
0382             displayMarginEnd: Maui.Style.toolBarHeight * 4
0383             
0384             boundsBehavior: Flickable.StopAtBounds
0385             boundsMovement: Flickable.StopAtBounds
0386             
0387             //                interactive: Maui.Handy.isTouch
0388             interactive: false
0389             highlightFollowsCurrentItem: true
0390             highlightMoveDuration: 0
0391             highlightResizeDuration : 0
0392             
0393             keyNavigationEnabled : true
0394             keyNavigationWraps : true
0395             Keys.onPressed: (event) => control.keyPress(event)
0396             
0397             Maui.Holder
0398             {
0399                 id: _holder
0400                 visible: false
0401                 anchors.fill : parent
0402                 
0403                 anchors.topMargin: _listView.headerItem ? _listView.headerItem.height : 0
0404                 anchors.bottomMargin: _listView.footerItem ?  _listView.footerItem.height : 0
0405             }
0406             
0407             Item
0408             {
0409                 anchors.fill: parent
0410                 z: parent.z-1
0411                 clip: false
0412                 
0413                 Loader
0414                 {
0415                     asynchronous: true
0416                     anchors.fill: parent
0417                     //                active: !Maui.Handy.hasTransientTouchInput && !Maui.Handy.isMobile
0418                     
0419                     sourceComponent: MouseArea
0420                     {
0421                         id: _mouseArea
0422                         
0423                         propagateComposedEvents: true
0424                         preventStealing: true
0425                         acceptedButtons: Qt.RightButton | Qt.LeftButton
0426                         
0427                         onClicked: (mouse) =>
0428                         {
0429                             console.log("Area clicked")
0430                             
0431                             control.areaClicked(mouse)
0432                             control.forceActiveFocus()
0433                             
0434                             if(mouse.button === Qt.RightButton)
0435                             {
0436                                 control.areaRightClicked()
0437                                 return
0438                             }
0439                         }
0440                         
0441                         onPositionChanged: (mouse) =>
0442                         {
0443                             if(_mouseArea.pressed && control.enableLassoSelection && selectLayer.visible)
0444                             {
0445                                 if(mouseX >= selectLayer.newX)
0446                                 {
0447                                     selectLayer.width = (mouseX + 10) < (control.x + control.width) ? (mouseX - selectLayer.x) : selectLayer.width;
0448                                 } else {
0449                                     selectLayer.x = mouseX < control.x ? control.x : mouseX;
0450                                     selectLayer.width = selectLayer.newX - selectLayer.x;
0451                                 }
0452                                 
0453                                 if(mouseY >= selectLayer.newY) {
0454                                     selectLayer.height = (mouseY + 10) < (control.y + control.height) ? (mouseY - selectLayer.y) : selectLayer.height;
0455                                     if(!_listView.atYEnd &&  mouseY > (control.y + control.height))
0456                                         _listView.contentY += 10
0457                                 } else {
0458                                     selectLayer.y = mouseY < control.y ? control.y : mouseY;
0459                                     selectLayer.height = selectLayer.newY - selectLayer.y;
0460                                     
0461                                     if(!_listView.atYBeginning && selectLayer.y === 0)
0462                                         _listView.contentY -= 10
0463                                 }
0464                             }
0465                         }
0466                         
0467                         onPressed: (mouse) =>
0468                         {
0469                             if (mouse.source === Qt.MouseEventNotSynthesized && control.enableLassoSelection && mouse.button === Qt.LeftButton && control.count > 0)
0470                             {
0471                                 selectLayer.visible = true;
0472                                 selectLayer.x = mouseX;
0473                                 selectLayer.y = mouseY;
0474                                 selectLayer.newX = mouseX;
0475                                 selectLayer.newY = mouseY;
0476                                 selectLayer.width = 0
0477                                 selectLayer.height = 0;
0478                             }
0479                         }
0480                         
0481                         onPressAndHold: (mouse) =>
0482                         {
0483                             if ( mouse.source !== Qt.MouseEventNotSynthesized && control.enableLassoSelection && !selectLayer.visible && !Maui.Handy.hasTransientTouchInput && !Maui.Handy.isAndroid)
0484                             {
0485                                 selectLayer.visible = true;
0486                                 selectLayer.x = mouseX;
0487                                 selectLayer.y = mouseY;
0488                                 selectLayer.newX = mouseX;
0489                                 selectLayer.newY = mouseY;
0490                                 selectLayer.width = 0
0491                                 selectLayer.height = 0;
0492                                 mouse.accepted = true
0493                             }else
0494                             {
0495                                 mouse.accepted = false
0496                             }
0497                         }
0498                         
0499                         onReleased: (mouse) =>
0500                         {
0501                             if(mouse.button !== Qt.LeftButton || !control.enableLassoSelection || !selectLayer.visible)
0502                             {
0503                                 mouse.accepted = false
0504                                 return;
0505                             }
0506                             
0507                             if(selectLayer.y > _listView.contentHeight)
0508                             {
0509                                 return selectLayer.reset();
0510                             }
0511                             
0512                             var lassoIndexes = []
0513                             var limitY =  mouse.y === lassoRec.y ?  lassoRec.y+lassoRec.height : mouse.y
0514                             var y = lassoRec.y
0515                             for(y; y < limitY; y+=10)
0516                             {
0517                                 const index = _listView.indexAt(_listView.width/2,y+_listView.contentY)
0518                                 if(!lassoIndexes.includes(index) && index>-1 && index< _listView.count)
0519                                     lassoIndexes.push(index)
0520                             }
0521                             
0522                             control.itemsSelected(lassoIndexes)
0523                             console.log("INDEXES << " , lassoIndexes, lassoRec.y, limitY)
0524                             selectLayer.reset()
0525                         }
0526                     }
0527                 }
0528             }
0529             
0530             Maui.Rectangle
0531             {
0532                 id: selectLayer
0533                 property int newX: 0
0534                 property int newY: 0
0535                 height: 0
0536                 width: 0
0537                 x: 0
0538                 y: 0
0539                 visible: false
0540                 color: Qt.rgba(control.Maui.Theme.highlightColor.r,control.Maui.Theme.highlightColor.g, control.Maui.Theme.highlightColor.b, 0.2)
0541                 opacity: 0.7
0542                 
0543                 borderColor: control.Maui.Theme.highlightColor
0544                 borderWidth: 2
0545                 solidBorder: false
0546                 
0547                 function reset()
0548                 {
0549                     selectLayer.x = 0;
0550                     selectLayer.y = 0;
0551                     selectLayer.newX = 0;
0552                     selectLayer.newY = 0;
0553                     selectLayer.visible = false;
0554                     selectLayer.width = 0;
0555                     selectLayer.height = 0;
0556                 }
0557             }
0558         }        
0559     }    
0560 }
0561 
0562