Warning, /maui/mauikit/src/controls.5/SelectionBar.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 2.14
0021 import QtQuick.Controls 2.14
0022 import QtQuick.Layouts 1.3
0023 import QtQuick.Window 2.15
0024 
0025 import org.mauikit.controls 1.3 as Maui
0026 
0027 import QtGraphicalEffects 1.0
0028 import QtQuick.Templates 2.15 as T
0029 
0030 /**
0031  * SelectionBar
0032  *
0033  * A bar to group selected items with a list of actions to perform to the selection.
0034  * The list of actions is  positioned into a Kirigami ActionToolBar.
0035  * This control provides methods to append and query elements added to it. To add elements to it, it is necesary to map them,
0036  * so an item is mapped to an unique id refered here as an URI.
0037  */
0038 Item
0039 {
0040     id: control
0041 
0042     implicitHeight: _layout.implicitHeight + Maui.Style.space.big
0043     implicitWidth: _layout.implicitWidth
0044 
0045     readonly property bool hidden : count === 0
0046 
0047     onHiddenChanged:
0048     {
0049         if(hidden && !singleSelection)
0050         {
0051             control.close()
0052         }else
0053         {
0054             control.open()
0055         }
0056     }
0057 
0058     visible: false
0059     focus: true
0060     Keys.enabled: true
0061     /**
0062      * actions : list<Action>
0063      * Default list of actions, the actions are positioned into a Kirigami ActionToolBar.
0064      */
0065     default property list<Action> actions
0066 
0067     /**
0068      * hiddenActions : list<Action>
0069      * List of action that wont be shown, and instead will always hidden and listed in the overflow menu.
0070      */
0071     property list<Action> hiddenActions
0072 
0073 
0074     /**
0075      * display : int
0076      * Preferred display mode of the visible actions. As icons only, or text beside icons... etc.
0077      */
0078     property int display : ToolButton.TextBesideIcon
0079 
0080     /**
0081      * maxListHeight : int
0082      * The selectionbar can list the grouped items under a collapsable list. This property defines the maximum height the list can take.
0083      * This can be changed to avoid overlapping the list with other components.
0084      */
0085     property int maxListHeight : 400
0086 
0087     /**
0088      * radius : int
0089      * By default the selectionbar was designed to be floating and thus has a rounded border corners.
0090      * This property allows to change the border radius.
0091      */
0092     property int radius: Maui.Style.radiusV
0093 
0094     /**
0095      * singleSelection : bool
0096      * if singleSelection is set to true then only a single item can be appended,
0097      * if another item is added then it replaces the previous one.
0098      **/
0099     property bool singleSelection: false
0100 
0101     /**
0102      * uris : var
0103      * List of URIs associated to the grouped elements.
0104      */
0105     readonly property alias uris: _private._uris
0106 
0107     /**
0108      * items : var
0109      * List of items grouped.
0110      */
0111     readonly property alias items: _private._items
0112 
0113     /**
0114      * count : int
0115      * Size of the elements grouped.
0116      */
0117     readonly property alias count : _urisModel.count
0118 
0119     //     /**
0120     //      * background : Rectangle
0121     //      * The default style of the background. This can be customized by changing its properties.
0122     //      */
0123     //     property alias background : bg
0124 
0125     /**
0126      * listDelegate : Component
0127      * Delegate to be used in the component where the grouped elements are listed.
0128      */
0129     property Component listDelegate: Maui.ListBrowserDelegate
0130     {
0131         id: delegate
0132         height: Maui.Style.rowHeight * 1.5
0133         width: ListView.view.width
0134 
0135         Maui.Theme.backgroundColor: "transparent"
0136         Maui.Theme.textColor: control.Maui.Theme.textColor
0137 
0138         iconVisible: false
0139         label1.text: model.uri
0140 
0141         checkable: true
0142         checked: true
0143         onToggled: control.removeAtIndex(index)
0144 
0145         onClicked: control.itemClicked(index)
0146         onPressAndHold: control.itemPressAndHold(index)
0147     }
0148 
0149     /**
0150      * cleared :
0151      * Triggered when the selection is cleared by using the close button or calling the clear method.
0152      */
0153     signal cleared()
0154 
0155     /**
0156      * exitClicked :
0157      * Triggered when the selection bar is closed by using the close button or the close method.
0158      */
0159     signal exitClicked()
0160 
0161     /**
0162      * itemClicked :
0163      * Triggered when an item in the selection list view is clicked.
0164      */
0165     signal itemClicked(int index)
0166 
0167     /**
0168      * itemPressAndHold :
0169      * Triggered when an item in the selection list view is pressed and hold.
0170      */
0171     signal itemPressAndHold(int index)
0172 
0173     /**
0174      * itemAdded :
0175      * Triggered when an item newly added to the selection.
0176      */
0177     signal itemAdded(var item)
0178 
0179     /**
0180      * itemRemoved :
0181      * Triggered when an item has been removed from the selection.
0182      */
0183     signal itemRemoved(var item)
0184 
0185     /**
0186      * uriAdded :
0187      * Triggered when an item newly added to the selection. This signal only sends the refered URI of the item.
0188      */
0189     signal uriAdded(string uri)
0190 
0191     /** uriRemoved:
0192      * Triggered when an item has been removed from the selection. This signal only sends the refered URI of the item.
0193      */
0194     signal uriRemoved(string uri)
0195 
0196     /**
0197      * clicked :
0198      * Triggered when an empty area of the selectionbar has been clicked.
0199      */
0200     signal clicked(var mouse)
0201 
0202     /**
0203      * rightClicked :
0204      * Triggered when an empty area of the selectionbar has been right clicked.
0205      */
0206     signal rightClicked(var mouse)
0207 
0208     /**
0209      * urisDropped :
0210      * Triggered when a group of URIs has been dropped.
0211      */
0212     signal urisDropped(var uris)
0213 
0214     property QtObject m_private : QtObject
0215     {
0216         id: _private
0217         property var _uris : []
0218         property var _items : []
0219     }
0220 
0221     ListModel
0222     {
0223         id: _urisModel
0224     }
0225 
0226     Loader
0227     {
0228         id: _loader
0229         active: control.visible
0230     }
0231 
0232     Component
0233     {
0234         id: _listContainerComponent
0235 
0236         Popup
0237         {
0238             parent: control
0239             closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
0240             modal: true
0241             height: Math.min(Math.min(400, control.maxListHeight), selectionList.contentHeight) + Maui.Style.space.big
0242             width: Math.min(600, control.Window.window.width)
0243 
0244             y: ((height) * -1) - Maui.Style.space.big
0245             x: Math.round( parent.width / 2 - width / 2 )
0246 
0247             Maui.ListBrowser
0248             {
0249                 id: selectionList
0250 
0251                 anchors.fill: parent
0252                 model: _urisModel
0253 
0254                 delegate: control.listDelegate
0255             }
0256         }
0257     }
0258 
0259         ParallelAnimation
0260         {
0261             id: _openAnimation
0262             NumberAnimation
0263             {
0264                 target: _layout
0265                 property: "y"
0266                 from: _layout.height
0267                 to: Maui.Style.space.big/2
0268                 duration: Maui.Style.units.longDuration*1
0269                 easing.type: Easing.OutBack
0270 
0271             }
0272 
0273             NumberAnimation
0274             {
0275                 target: _layout
0276                 property: "scale"
0277                 from: 0.5
0278                 to: 1
0279                 duration: Maui.Style.units.longDuration*1
0280                 easing.type: Easing.OutQuad
0281             }
0282 
0283             //NumberAnimation
0284             //{
0285             //target: _imp
0286             //property: "opacity"
0287             //from: 0
0288             //to: 1
0289             //duration: Maui.Style.units.longDuration*2
0290             //easing.type: Easing.InBack
0291             //}
0292         }
0293 
0294         ParallelAnimation
0295         {
0296             id: _closeAnimation
0297             NumberAnimation
0298             {
0299                 target: _layout
0300                 property: "y"
0301                 from: Maui.Style.space.big/2
0302                 to: _layout.height
0303                 duration: Maui.Style.units.longDuration*1
0304                 easing.type: Easing.InBack
0305 
0306             }
0307 
0308             NumberAnimation
0309             {
0310                 target: _layout
0311                 property: "scale"
0312                 from: 1
0313                 to: 0.5
0314                 duration: Maui.Style.units.longDuration*1
0315                 easing.type: Easing.InQuad
0316 
0317             }
0318 
0319             //NumberAnimation
0320             //{
0321             //target: _imp
0322             //property: "opacity"
0323             //from: 1
0324             //to: 0
0325             //duration: Maui.Style.units.longDuration*2
0326             //easing.type: Easing.OutBack
0327 
0328             //}
0329 
0330             onFinished: control.visible = false
0331         }
0332 
0333         Maui.ToolBar
0334         {
0335             id: _layout
0336             width: control.width
0337             padding: Maui.Style.space.medium
0338             forceCenterMiddleContent: false
0339             position: ToolBar.Footer
0340 
0341             leftContent: Maui.Badge
0342             {
0343                 id: _counter
0344                 text: control.count
0345                 radius: Maui.Style.radiusV
0346                 font.pointSize: Maui.Style.fontSizes.big
0347                 Maui.Theme.colorSet: control.Maui.Theme.colorSet
0348                 Maui.Theme.backgroundColor: _loader.item && _loader.item.visible ?
0349                                                     Maui.Theme.highlightColor : Qt.tint(control.Maui.Theme.textColor, Qt.rgba(control.Maui.Theme.backgroundColor.r, control.Maui.Theme.backgroundColor.g, control.Maui.Theme.backgroundColor.b, 0.9))
0350                 border.color: "transparent"
0351 
0352                 //                 onTextChanged: _counterAnimation.start()
0353                 //
0354                 //                     ColorAnimation on color
0355                 //                     {
0356                 //                         id:  _counterAnimation
0357                 //
0358                 //                         from: Maui.Theme.highlightColor
0359                 //                         to: Maui.Theme.backgroundColor
0360                 //                         loops:3
0361                 //                         easing {
0362                 //                             type: Easing.OutElastic
0363                 //                             amplitude: 1.0
0364                 //                             period: 0.5
0365                 //                         }
0366                 //                     }
0367 
0368                 onClicked:
0369                 {
0370                     _loader.sourceComponent = _listContainerComponent
0371                     _loader.item.open()
0372                 }
0373 
0374                 Maui.Rectangle
0375                 {
0376                     opacity: 0.3
0377                     anchors.fill: parent
0378                     anchors.margins: 4
0379                     visible: _counter.hovered
0380                     color: "transparent"
0381                     borderColor: "white"
0382                     solidBorder: false
0383                 }
0384 
0385                 MouseArea
0386                 {
0387                     id: _mouseArea
0388                     anchors.fill: parent
0389                     propagateComposedEvents: true
0390                     property int startX
0391                     property int startY
0392                     Drag.active: drag.active
0393                     Drag.hotSpot.x: 0
0394                     Drag.hotSpot.y: 0
0395                     Drag.dragType: Drag.Automatic
0396                     Drag.supportedActions: Qt.CopyAction
0397                     Drag.keys: ["text/plain","text/uri-list"]
0398 
0399                     onPressed:
0400                     {
0401                         if( mouse.source !== Qt.MouseEventSynthesizedByQt)
0402                         {
0403                             drag.target = _counter
0404                             _counter.grabToImage(function(result)
0405                             {
0406                                 _mouseArea.Drag.imageSource = result.url
0407                             })
0408 
0409                             _mouseArea.Drag.mimeData = { "text/uri-list": control.uris.join("\n")}
0410 
0411                             startX = _counter.x
0412                             startY = _counter.y
0413 
0414                         }else mouse.accepted = false
0415                     }
0416 
0417                     onReleased :
0418                     {
0419                         _counter.x = startX
0420                         _counter.y = startY
0421                     }
0422 
0423                 }
0424             }
0425 
0426             Repeater
0427             {
0428                 model: control.actions
0429 
0430                 ToolButton
0431                 {
0432                     action: modelData
0433                     display: control.display
0434                     ToolTip.delay: 1000
0435                     ToolTip.timeout: 5000
0436                     ToolTip.visible: hovered || pressed && action.text
0437                     ToolTip.text: action.text
0438                 }
0439             }
0440 
0441             Maui.ToolButtonMenu
0442             {
0443                 icon.name: "overflow-menu"
0444                 visible: control.hiddenActions.length > 0
0445                 Repeater
0446                 {
0447                     model:  control.hiddenActions
0448                     delegate: MenuItem{ action: modelData}
0449                 }
0450             }
0451 
0452            rightContent: Maui.CloseButton
0453             {
0454                 onClicked:
0455                 {
0456                     control.exitClicked()
0457                 }
0458             }
0459 
0460             background: Rectangle
0461             {
0462                 id: bg
0463                 color: Maui.Theme.backgroundColor
0464                 radius: control.radius
0465 
0466                 Behavior on color
0467                 {
0468                     Maui.ColorTransition {  }
0469                 }
0470 
0471                 MouseArea
0472                 {
0473                     anchors.fill: parent
0474                     acceptedButtons: Qt.RightButton | Qt.LeftButton
0475                     propagateComposedEvents: false
0476                     preventStealing: true
0477 
0478                     onClicked:
0479                     {
0480                         if(!Maui.Handy.isMobile && mouse.button === Qt.RightButton)
0481                             control.rightClicked(mouse)
0482                             else
0483                                 control.clicked(mouse)
0484                     }
0485 
0486                     onPressAndHold :
0487                     {
0488                         if(Maui.Handy.isMobile)
0489                             control.rightClicked(mouse)
0490                     }
0491                 }
0492 
0493                 Maui.Rectangle
0494                 {
0495                     opacity: 0.2
0496                     anchors.fill: parent
0497                     anchors.margins: 4
0498                     visible: _dropArea.containsDrag
0499                     color: "transparent"
0500                     borderColor: Maui.Theme.textColor
0501                     solidBorder: false
0502                 }
0503 
0504                 DropArea
0505                 {
0506                     id: _dropArea
0507                     anchors.fill: parent
0508                     onDropped:
0509                     {
0510                         control.urisDropped(drop.urls)
0511                     }
0512                 }
0513 
0514                 layer.enabled: true
0515                 layer.effect: DropShadow
0516                 {
0517                     cached: true
0518                     horizontalOffset: 0
0519                     verticalOffset: 0
0520                     radius: 8.0
0521                     samples: 16
0522                     color:  "#80000000"
0523                     smooth: true
0524                 }
0525             }
0526         }
0527 
0528     Keys.onEscapePressed:
0529     {
0530         control.exitClicked();
0531     }
0532 
0533     Keys.onBackPressed:
0534     {
0535         control.exitClicked();
0536         event.accepted = true
0537     }
0538 
0539     /**
0540      * Removes all the items from the selection.
0541      */
0542     function clear()
0543     {
0544         _private._uris = []
0545         _private._items = []
0546         _urisModel.clear()
0547         control.cleared()
0548     }
0549 
0550     /**
0551      * Returns an item at a given index
0552      */
0553     function itemAt(index)
0554     {
0555         if(index < 0 ||  index > control.count)
0556         {
0557             return
0558         }
0559         return _urisModel.get(index)
0560     }
0561 
0562     /**
0563      * Remove a single item at a given index
0564      */
0565     function removeAtIndex(index)
0566     {
0567         if(index < 0)
0568         {
0569             return
0570         }
0571 
0572         const item = _urisModel.get(index)
0573         const uri = item.uri
0574 
0575         if(contains(uri))
0576         {
0577             _private._uris.splice(index, 1)
0578             _private._items.splice(index, 1)
0579             _urisModel.remove(index)
0580             control.itemRemoved(item)
0581             control.uriRemoved(uri)
0582         }
0583     }
0584 
0585     /**
0586      * Removes an item from thge selection at a given URI
0587      */
0588     function removeAtUri(uri)
0589     {
0590         removeAtIndex(indexOf(uri))
0591     }
0592 
0593     /**
0594      *  Return the index of an item in the selection given its URI
0595      */
0596     function indexOf(uri)
0597     {
0598         return _private._uris.indexOf(uri)
0599     }
0600 
0601     /**
0602      * Append a new item to the selection associated to the given URI
0603      */
0604     function append(uri, item)
0605     {
0606         if(control.singleSelection)
0607         {
0608             clear()
0609         }
0610 
0611         if(!contains(uri) || control.singleSelection)
0612         {
0613             _private._items.push(item)
0614             _private._uris.push(uri)
0615 
0616             item.uri = uri
0617             _urisModel.append(item)
0618             control.itemAdded(item)
0619             control.uriAdded(uri)
0620         }
0621     }
0622 
0623     /**
0624      * Returns a single string with all the URIs separated by a comma.
0625      */
0626     function getSelectedUrisString()
0627     {
0628         return String(""+_private._uris.join(","))
0629     }
0630 
0631     /**
0632      * Returns true if the selection contains an item associated to a given URI.
0633      */
0634     function contains(uri)
0635     {
0636         return _private._uris.includes(uri)
0637     }
0638 
0639     function open()
0640     {
0641         if(control.visible)
0642         {
0643             return;
0644         }
0645 
0646         control.visible = true
0647         _openAnimation.start()
0648     }
0649 
0650     function close()
0651     {
0652         if(!control.visible)
0653         {
0654             return
0655         }
0656         _closeAnimation.start()
0657     }
0658 }