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

0001 import QtQuick
0002 import QtQuick.Controls
0003 import QtQuick.Layouts
0004 import QtQml
0005 
0006 import org.mauikit.controls 1.3 as Maui
0007 
0008 /**
0009  * @inherit QtQuick.Controls.Control
0010  * @brief A set of grouped action visually joined together. 
0011  * 
0012  * <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-control.html">This control inherits from QQC2 Control, to checkout its inherited properties refer to the Qt Docs.</a> 
0013  * 
0014  * The set actions can be checkable and auto-exclusive or not.
0015  * 
0016  * @image html Misc/toolactions.png "[1] Non-checkable. [2] Checkable non-auto-exclusive. [3] Checkable and autoexclusive"
0017  * 
0018  * @section features Features
0019  * This control supports checkable and non-checkable actions. Also auto-exclusive and non-auto-exclusive actions.
0020  * 
0021  * When enabling the `autoExclusive` property, then only one action in the group can be marked as checked at the time.
0022  * 
0023  * There is also the option to collapse the actions into a single button with a popup menu where the actions are listed, this is useful when the available space changes and the control needs to be made more compact to save space.
0024  * 
0025  * @image html Misc/toolactions2.png "The collapsed actions into a menu"
0026  * 
0027  * If only two actions are added and marked as auto-exclusive, then this control has the option to enable a `cyclic` behavior, which means that toggling one button will activate the next action in line and cyclic around.
0028  * @see canCyclic
0029  * @see cyclic
0030  * 
0031  * Heres a example of how to achieve such behavior:
0032  * @code
0033  * Maui.ToolActions
0034  * {
0035  *    id: _actions
0036  *    checkable: true
0037  *    autoExclusive: true
0038  *    cyclic: true //enable the cyclic behavior
0039  *    expanded: false //the cyclic behavior needs to be in the collapsed mode
0040  * 
0041  *    property int currentAction: 0 //here we keep the state for the current action checked
0042  * 
0043  *    Action
0044  *    {
0045  *        id: _action1
0046  *        icon.name: "view-list-details"
0047  *        checked: _actions.currentAction === 0
0048  *        onTriggered:
0049  *        {
0050  *            _actions.currentAction = 0
0051  *        }
0052  *    }
0053  * 
0054  *    Action
0055  *    {
0056  *        id: _action2
0057  *        icon.name: "view-list-icons"
0058  *        checked: _actions.currentAction === 1
0059  *        onTriggered:
0060  *        {
0061  *            _actions.currentAction = 1
0062  *        }
0063  *    }
0064  * }
0065  * @endcode
0066  * 
0067  * @code
0068  * Maui.ToolActions
0069  * {
0070  *    checkable: true
0071  *    autoExclusive: true
0072  *    
0073  *    Action
0074  *    {
0075  *        text: "Pick"
0076  *    }
0077  *    
0078  *    Action
0079  *    {
0080  *        text: "Only"
0081  *    }
0082  *    
0083  *    Action
0084  *    {
0085  *        text: "One"
0086  *    }
0087  * }
0088  * @endcode
0089  * 
0090  * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/ToolActions.qml">You can find a more complete example at this link.</a>
0091  */
0092 Control
0093 {
0094     id: control
0095     
0096     implicitWidth: implicitContentWidth + leftPadding + rightPadding
0097     implicitHeight: implicitContentHeight + topPadding + bottomPadding
0098     
0099     opacity: enabled ? 1 : 0.5
0100     
0101     spacing: 2
0102     padding: 0
0103     
0104     Maui.Theme.colorSet: Maui.Theme.Button
0105     Maui.Theme.inherit: false
0106     
0107     /**
0108      * @brief The list of QQC2 Action to be listed. These can be declared a children elements of this control.
0109      */
0110     default property list<Action> actions
0111     
0112     /**
0113      * @brief Whether this control should only allow one action to be checked at the time.
0114      * By default this is set to `true`
0115      */
0116     property bool autoExclusive: true
0117     
0118     /**
0119      * @brief Whether the action button can be checked. If enabled, then the state will be styled accordingly.
0120      * @By default this is set to `true`.
0121      */
0122     property bool checkable: true
0123     
0124     /**
0125      * @brief Options on how to display the button text and icon.
0126      * Available options are:
0127      * - ToolButton.IconOnly
0128      * - ToolButton.TextBesideIcon
0129      * - ToolButton.TextOnly
0130      * - ToolButton.TextUnderIcon
0131      * By default this is set to `ToolButton.TextBesideIcon`
0132      */
0133     property int display: ToolButton.TextBesideIcon
0134     
0135     /**
0136      * @brief Whether two action can be triggered in a cyclic manner. So one press will activate the next action and then cycle around again.
0137      * @see canCyclic
0138      * By default this is set to `false`
0139      */
0140     property bool cyclic: false
0141     
0142     /**
0143      * @brief Whether the `cyclic` behavior can be activated.
0144      * For it to be possible, the conditions are: only two actions and those must be auto-exclusive.
0145      * @see cyclic
0146      * @see autoExclusive
0147      * @see count
0148      */
0149     readonly property bool canCyclic : control.cyclic && control.count === 2  && control.autoExclusive
0150     
0151     /**
0152      * @brief Whether the style of this control should be styled as flat.
0153      * By default this is set to `false`.
0154      */
0155     property bool flat : false
0156     
0157     /**
0158      * @brief The total amount of actions declared.
0159      */
0160     readonly property int count : actions.length
0161     
0162     
0163     /**
0164      * @brief Whether the control should display all the actions as buttons in a  row, or to collapse them into a popup menu.
0165      * By default this is set to `true`.
0166      */
0167     property bool expanded : true
0168     
0169     /**
0170      * @brief The icon name to be used in the button that opens the menu popup, when the view is collapsed.
0171      * By default this is set to `application-menu`.
0172      */
0173     property string defaultIconName: "application-menu"
0174     
0175     /**
0176      * @brief Forces to uncheck all the actions except the one action sent as the argument.
0177      * @param except the action that should not be unchecked.
0178      */
0179     function uncheck(except)
0180     {
0181         for(var i in control.actions)
0182         {
0183             if(control.actions[i] === except)
0184             {
0185                 continue
0186             }
0187             
0188             control.actions[i].checked = false
0189         }
0190     }
0191     
0192     contentItem: Loader
0193     {
0194         id: _loader
0195         asynchronous: true
0196         sourceComponent: control.expanded ? _rowComponent : _buttonComponent
0197     }
0198     
0199     background: null
0200     
0201     Component
0202     {
0203         id: _rowComponent
0204         
0205         Row
0206         {
0207             id: _row
0208             property int biggerHeight : 0
0209             spacing: control.spacing
0210             
0211             Behavior on width
0212             {
0213                 enabled: Maui.Style.enableEffects
0214                 
0215                 NumberAnimation
0216                 {
0217                     duration: Maui.Style.units.shortDuration
0218                     easing.type: Easing.InOutQuad
0219                 }
0220             }
0221             
0222             function calculateBiggerHeight()
0223             {
0224                 var value = 0
0225                 for(var i in _row.children)
0226                 {
0227                     const height = _row.children[i].implicitHeight
0228                     if(height > value)
0229                     {
0230                         value = height
0231                     }
0232                 }
0233                 
0234                 return value
0235             }
0236             
0237             Repeater
0238             {
0239                 id: _repeater
0240                 model: control.actions
0241                 
0242                 ToolButton
0243                 {
0244                     id: _actionButton
0245                     action : modelData
0246                     checkable: control.checkable || action.checkable
0247                     
0248                     height: Math.max(implicitHeight, _row.biggerHeight)
0249                     
0250                     onImplicitHeightChanged: _row.biggerHeight = _row.calculateBiggerHeight()
0251                     
0252                     autoExclusive: control.autoExclusive
0253                     enabled: action.enabled
0254                     
0255                     display: control.display
0256                     
0257                     background: Maui.ShadowedRectangle
0258                     {
0259                         color:  (checked || down ? Maui.Theme.highlightColor : ( hovered ? Maui.Theme.hoverColor : Maui.Theme.backgroundColor))
0260                         corners
0261                         {
0262                             topLeftRadius: index === 0 ? Maui.Style.radiusV : 0
0263                             topRightRadius: index === _repeater.count - 1 ? Maui.Style.radiusV : 0
0264                             bottomLeftRadius: index === 0 ? Maui.Style.radiusV : 0
0265                             bottomRightRadius:  index === _repeater.count - 1 ? Maui.Style.radiusV : 0
0266                         }
0267                         
0268                         Behavior on color
0269                         {
0270                             Maui.ColorTransition{}
0271                         }
0272                     }
0273                 }
0274             }
0275         }
0276     }
0277     
0278     Component
0279     {
0280         id: _buttonComponent
0281         
0282         ToolButton
0283         {
0284             id: _defaultButtonIcon
0285             
0286             property Action m_action
0287             
0288             Component.onCompleted: _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
0289             
0290             function buttonAction()
0291             {
0292                 if(control.autoExclusive)
0293                 {
0294                     var currentAction
0295                     var actionIndex = -1
0296                     for(var i in control.actions)
0297                     {
0298                         console.log("Checking current action", i)
0299                         if(control.actions[i].checked)
0300                         {
0301                             actionIndex = i
0302                             currentAction = control.actions[actionIndex]
0303                             console.log("Found current action", i, actionIndex)
0304                         }
0305                     }
0306                     
0307                     if(control.canCyclic)
0308                     {
0309                         actionIndex++
0310                         
0311                         let m_index = actionIndex >= control.actions.length ? 0 : actionIndex
0312                         //
0313                         console.log("Setting current action at", m_index)
0314                         if(control.actions[m_index].enabled)
0315                         {
0316                             return control.actions[m_index];
0317                         }
0318                     }
0319                     
0320                     return currentAction
0321                 }
0322                 
0323                 return null
0324             }
0325             
0326             Row
0327             {
0328                 visible: false
0329                 Repeater
0330                 {
0331                     model: control.actions
0332                     delegate: Item
0333                     {
0334                         property bool checked : modelData.checked
0335                         onCheckedChanged: _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
0336                     }
0337                 }
0338             }
0339             
0340             data: Maui.ContextualMenu
0341             {
0342                 id: _menu
0343                 
0344                 Repeater
0345                 {
0346                     model: control.autoExclusive && control.canCyclic ? undefined : control.actions
0347                     
0348                     delegate: MenuItem
0349                     {
0350                         action: modelData
0351                         enabled: modelData.enabled
0352                         autoExclusive: control.autoExclusive
0353                         checkable: control.checkable || action.checkable
0354                     }
0355                 }
0356             }
0357             
0358             onClicked:
0359             {
0360                 if(_defaultButtonIcon.m_action && control.canCyclic && control.autoExclusive)
0361                 {
0362                     console.log("Trigger next cyclic action", _defaultButtonIcon.m_action.icon.name)
0363                     // var previousAction = _defaultButtonIcon.action
0364                     _defaultButtonIcon.m_action.triggered()
0365                     _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
0366                     
0367                 }else
0368                 {
0369                     if(!_menu.visible)
0370                     {
0371                         _menu.show(0, control.height, control)
0372                         
0373                     }else
0374                     {
0375                         _menu.close()
0376                     }
0377                 }
0378             }
0379             
0380             icon.width:  Maui.Style.iconSize
0381             icon.height: Maui.Style.iconSize
0382             icon.color: m_action ? (m_action.icon.color && m_action.icon.color.length ? m_action.icon.color : (pressed ? control.Maui.Theme.highlightColor : control.Maui.Theme.textColor)) :  control.Maui.Theme.textColor
0383             
0384             icon.name: m_action ? m_action.icon.name : control.defaultIconName
0385             text: m_action ? m_action.text: ""
0386             
0387             enabled: m_action ? m_action.enabled : true
0388             
0389             subMenu: !control.canCyclic
0390             
0391             display: control.display
0392             
0393             checkable: control.checkable && (action ? action.checkable : false)
0394             
0395             background: Rectangle
0396             {
0397                 color: Maui.Theme.backgroundColor
0398                 radius: Maui.Style.radiusV
0399                 
0400                 Behavior on color
0401                 {
0402                     Maui.ColorTransition{}
0403                 }
0404             }
0405         }        
0406     }
0407 }