aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquickactiongroup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquickactiongroup.cpp')
-rw-r--r--src/quicktemplates2/qquickactiongroup.cpp480
1 files changed, 480 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquickactiongroup.cpp b/src/quicktemplates2/qquickactiongroup.cpp
new file mode 100644
index 00000000..64895689
--- /dev/null
+++ b/src/quicktemplates2/qquickactiongroup.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickactiongroup_p.h"
+
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvariant.h>
+#include <QtQml/qqmlinfo.h>
+
+#include "qquickaction_p.h"
+#include "qquickaction_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ActionGroup
+ \inherits QtObject
+ \instantiates QQuickActionGroup
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \ingroup utilities
+ \brief Groups actions together.
+
+ ActionGroup is a non-visual group of actions. A mutually \l exclusive
+ action group is used with actions where only one of the options can be
+ selected at a time.
+
+ The most straight-forward way to use ActionGroup is to declare actions
+ as children of the group.
+
+ \code
+ ActionGroup {
+ id: alignmentGroup
+
+ Action {
+ checked: true
+ checkable: true
+ text: qsTr("Left")
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Center")
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Right")
+ }
+ }
+ \endcode
+
+ Alternatively, the \l group attached property allows declaring the actions
+ elsewhere and assigning them to a specific group.
+
+ \code
+ ActionGroup { id: alignmentGroup }
+
+ Action {
+ checked: true
+ checkable: true
+ text: qsTr("Left")
+ ActionGroup.group: alignmentGroup
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Center")
+ ActionGroup.group: alignmentGroup
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Right")
+ ActionGroup.group: alignmentGroup
+ }
+ \endcode
+
+ More advanced use cases can be handled using the \c addAction() and
+ \c removeAction() methods.
+
+ \sa Action, ButtonGroup
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::ActionGroup::triggered(Action action)
+
+ This signal is emitted when an \a action in the group has been triggered.
+
+ This signal is convenient for implementing a common signal handler for
+ all actions in the same group.
+
+ \code
+ ActionGroup {
+ onTriggered: console.log("triggered:", action.text)
+
+ Action { text: "First" }
+ Action { text: "Second" }
+ Action { text: "Third" }
+ }
+ \endcode
+
+ \sa Action::triggered()
+*/
+
+class QQuickActionGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickActionGroup)
+
+public:
+ QQuickActionGroupPrivate()
+ : enabled(true),
+ exclusive(true),
+ checkedAction(nullptr)
+ {
+ }
+
+ void clear();
+ void actionTriggered();
+ void _q_updateCurrent();
+
+ static bool changeEnabled(QQuickAction *action, bool enabled);
+
+ static void actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj);
+ static int actions_count(QQmlListProperty<QQuickAction> *prop);
+ static QQuickAction *actions_at(QQmlListProperty<QQuickAction> *prop, int index);
+ static void actions_clear(QQmlListProperty<QQuickAction> *prop);
+
+ bool enabled;
+ bool exclusive;
+ QPointer<QQuickAction> checkedAction;
+ QVector<QQuickAction*> actions;
+};
+
+void QQuickActionGroupPrivate::clear()
+{
+ for (QQuickAction *action : qAsConst(actions)) {
+ QQuickActionPrivate::get(action)->group = nullptr;
+ QObjectPrivate::disconnect(action, &QQuickAction::triggered, this, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, this, &QQuickActionGroupPrivate::_q_updateCurrent);
+ }
+ actions.clear();
+}
+
+void QQuickActionGroupPrivate::actionTriggered()
+{
+ Q_Q(QQuickActionGroup);
+ QQuickAction *action = qobject_cast<QQuickAction*>(q->sender());
+ if (action)
+ emit q->triggered(action);
+}
+
+void QQuickActionGroupPrivate::_q_updateCurrent()
+{
+ Q_Q(QQuickActionGroup);
+ if (!exclusive)
+ return;
+ QQuickAction *action = qobject_cast<QQuickAction*>(q->sender());
+ if (action && action->isChecked())
+ q->setCheckedAction(action);
+ else if (!actions.contains(checkedAction))
+ q->setCheckedAction(nullptr);
+}
+
+bool QQuickActionGroupPrivate::changeEnabled(QQuickAction *action, bool enabled)
+{
+ return action->isEnabled() != enabled && (!enabled || !QQuickActionPrivate::get(action)->explicitEnabled);
+}
+
+void QQuickActionGroupPrivate::actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj)
+{
+ QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object);
+ q->addAction(obj);
+}
+
+int QQuickActionGroupPrivate::actions_count(QQmlListProperty<QQuickAction> *prop)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ return p->actions.count();
+}
+
+QQuickAction *QQuickActionGroupPrivate::actions_at(QQmlListProperty<QQuickAction> *prop, int index)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ return p->actions.value(index);
+}
+
+void QQuickActionGroupPrivate::actions_clear(QQmlListProperty<QQuickAction> *prop)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ if (!p->actions.isEmpty()) {
+ p->clear();
+ QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object);
+ // QTBUG-52358: don't clear the checked action immediately
+ QMetaObject::invokeMethod(q, "_q_updateCurrent", Qt::QueuedConnection);
+ emit q->actionsChanged();
+ }
+}
+
+QQuickActionGroup::QQuickActionGroup(QObject *parent)
+ : QObject(*(new QQuickActionGroupPrivate), parent)
+{
+}
+
+QQuickActionGroup::~QQuickActionGroup()
+{
+ Q_D(QQuickActionGroup);
+ d->clear();
+}
+
+QQuickActionGroupAttached *QQuickActionGroup::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickActionGroupAttached(object);
+}
+
+/*!
+ \qmlproperty Action QtQuick.Controls::ActionGroup::checkedAction
+
+ This property holds the currently selected action in an exclusive group,
+ or \c null if there is none or the group is non-exclusive.
+
+ By default, it is the first checked action added to an exclusive action group.
+
+ \sa exclusive
+*/
+QQuickAction *QQuickActionGroup::checkedAction() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->checkedAction;
+}
+
+void QQuickActionGroup::setCheckedAction(QQuickAction *checkedAction)
+{
+ Q_D(QQuickActionGroup);
+ if (d->checkedAction == checkedAction)
+ return;
+
+ if (d->checkedAction)
+ d->checkedAction->setChecked(false);
+ d->checkedAction = checkedAction;
+ if (checkedAction)
+ checkedAction->setChecked(true);
+ emit checkedActionChanged();
+}
+
+/*!
+ \qmlproperty list<Action> QtQuick.Controls::ActionGroup::actions
+ \default
+
+ This property holds the list of actions in the group.
+
+ \sa group
+*/
+QQmlListProperty<QQuickAction> QQuickActionGroup::actions()
+{
+ Q_D(QQuickActionGroup);
+ return QQmlListProperty<QQuickAction>(this, d,
+ QQuickActionGroupPrivate::actions_append,
+ QQuickActionGroupPrivate::actions_count,
+ QQuickActionGroupPrivate::actions_at,
+ QQuickActionGroupPrivate::actions_clear);
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::ActionGroup::exclusive
+
+ This property holds whether the action group is exclusive. The default value is \c true.
+
+ If this property is \c true, then only one action in the group can be checked at any given time.
+ The user can trigger any action to check it, and that action will replace the existing one as
+ the checked action in the group.
+
+ In an exclusive group, the user cannot uncheck the currently checked action by triggering it;
+ instead, another action in the group must be triggered to set the new checked action for that
+ group.
+
+ In a non-exclusive group, checking and unchecking actions does not affect the other actions in
+ the group. Furthermore, the value of the \l checkedAction property is \c null.
+*/
+bool QQuickActionGroup::isExclusive() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->exclusive;
+}
+
+void QQuickActionGroup::setExclusive(bool exclusive)
+{
+ Q_D(QQuickActionGroup);
+ if (d->exclusive == exclusive)
+ return;
+
+ d->exclusive = exclusive;
+ emit exclusiveChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::ActionGroup::enabled
+
+ This property holds whether the action group is enabled. The default value is \c true.
+
+ If this property is \c false, then all actions in the group are disabled. If this property
+ is \c true, all actions in the group are enabled, unless explicitly disabled.
+*/
+bool QQuickActionGroup::isEnabled() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->enabled;
+}
+
+void QQuickActionGroup::setEnabled(bool enabled)
+{
+ Q_D(QQuickActionGroup);
+ if (d->enabled == enabled)
+ return;
+
+ for (QQuickAction *action : qAsConst(d->actions)) {
+ if (d->changeEnabled(action, enabled))
+ emit action->enabledChanged(enabled);
+ }
+
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::ActionGroup::addAction(Action action)
+
+ Adds an \a action to the action group.
+
+ \note Manually adding objects to a action group is typically unnecessary.
+ The \l actions property and the \l group attached property provide a
+ convenient and declarative syntax.
+
+ \sa actions, group
+*/
+void QQuickActionGroup::addAction(QQuickAction *action)
+{
+ Q_D(QQuickActionGroup);
+ if (!action || d->actions.contains(action))
+ return;
+
+ const bool enabledChange = d->changeEnabled(action, d->enabled);
+
+ QQuickActionPrivate::get(action)->group = this;
+ QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::connect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent);
+
+ if (d->exclusive && action->isChecked())
+ setCheckedAction(action);
+ if (enabledChange)
+ emit action->enabledChanged(action->isEnabled());
+
+ d->actions.append(action);
+ emit actionsChanged();
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::ActionGroup::removeAction(Action action)
+
+ Removes an \a action from the action group.
+
+ \note Manually removing objects from a action group is typically unnecessary.
+ The \l actions property and the \l group attached property provide a
+ convenient and declarative syntax.
+
+ \sa actions, group
+*/
+void QQuickActionGroup::removeAction(QQuickAction *action)
+{
+ Q_D(QQuickActionGroup);
+ if (!action || !d->actions.contains(action))
+ return;
+
+ const bool enabledChange = d->changeEnabled(action, d->enabled);
+
+ QQuickActionPrivate::get(action)->group = nullptr;
+ QObjectPrivate::disconnect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent);
+
+ if (d->checkedAction == action)
+ setCheckedAction(nullptr);
+ if (enabledChange)
+ emit action->enabledChanged(action->isEnabled());
+
+ d->actions.removeOne(action);
+ emit actionsChanged();
+}
+
+class QQuickActionGroupAttachedPrivate : public QObjectPrivate
+{
+public:
+ QQuickActionGroupAttachedPrivate() : group(nullptr) { }
+
+ QQuickActionGroup *group;
+};
+
+QQuickActionGroupAttached::QQuickActionGroupAttached(QObject *parent)
+ : QObject(*(new QQuickActionGroupAttachedPrivate), parent)
+{
+}
+
+/*!
+ \qmlattachedproperty ActionGroup QtQuick.Controls::ActionGroup::group
+
+ This property attaches an action to an action group.
+
+ \code
+ ActionGroup { id: group }
+
+ Action {
+ checked: true
+ text: qsTr("Option A")
+ ActionGroup.group: group
+ }
+
+ Action {
+ text: qsTr("Option B")
+ ActionGroup.group: group
+ }
+ \endcode
+
+ \sa actions
+*/
+QQuickActionGroup *QQuickActionGroupAttached::group() const
+{
+ Q_D(const QQuickActionGroupAttached);
+ return d->group;
+}
+
+void QQuickActionGroupAttached::setGroup(QQuickActionGroup *group)
+{
+ Q_D(QQuickActionGroupAttached);
+ if (d->group == group)
+ return;
+
+ if (d->group)
+ d->group->removeAction(qobject_cast<QQuickAction*>(parent()));
+ d->group = group;
+ if (group)
+ group->addAction(qobject_cast<QQuickAction*>(parent()));
+ emit groupChanged();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickactiongroup_p.cpp"