summaryrefslogtreecommitdiff
path: root/src/controls/qquickexclusivegroup.cpp
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@digia.com>2013-04-12 16:16:50 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-04-12 17:11:27 +0200
commit10947feec131b408dd7f5761d07d5e1cf4511728 (patch)
tree885ffe82539d649e1b1183f5cf3cafc1f532f9d2 /src/controls/qquickexclusivegroup.cpp
parent050fa849aeb60271a81544fc19c5eae668ec0c12 (diff)
downloadqtquickcontrols-10947feec131b408dd7f5761d07d5e1cf4511728.tar.gz
Rename QtExclusiveGroup to QQuickExclusiveGroup
Change-Id: Ic3b95c40d2698343fdeed30db5ad8a0ec3f8df22 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Diffstat (limited to 'src/controls/qquickexclusivegroup.cpp')
-rw-r--r--src/controls/qquickexclusivegroup.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/controls/qquickexclusivegroup.cpp b/src/controls/qquickexclusivegroup.cpp
new file mode 100644
index 00000000..e7ddb2d0
--- /dev/null
+++ b/src/controls/qquickexclusivegroup.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickexclusivegroup_p.h"
+
+#include <qvariant.h>
+#include <qdebug.h>
+#include "qquickaction_p.h"
+
+#define CHECKED_PROPERTY "checked"
+
+QT_BEGIN_NAMESPACE
+
+static const char *checkableSignals[] = {
+ CHECKED_PROPERTY"Changed()",
+ "toggled(bool)",
+ "toggled()",
+ 0
+};
+
+static bool isChecked(const QObject *o)
+{
+ if (!o) return false;
+ QVariant checkedVariant = o->property(CHECKED_PROPERTY);
+ return checkedVariant.isValid() && checkedVariant.toBool();
+}
+
+/*!
+ \qmltype ExclusiveGroup
+ \instantiates QQuickExclusiveGroup
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief ExclusiveGroup provides a way to declare several checkable controls as mutually exclusive.
+
+ ExclusiveGroup can contain several \l Action items, and those will automatically get their
+ \l Action::exclusiveGroup property assigned.
+
+ \code
+ ExclusiveGroup {
+ id: radioInputGroup
+
+ Action {
+ id: dabRadioInput
+ text: "DAB"
+ checkable: true
+ }
+
+ Action {
+ id: fmRadioInput
+ text: "FM"
+ checkable: true
+ }
+
+ Action {
+ id: amRadioInput
+ text: "AM"
+ checkable: true
+ }
+ }
+ \endcode
+
+ Several controls already support \l ExclusiveGroup, e.g. \l Action, \l MenuItem, \l Button, and \l RadioButton.
+
+ Since \l ExclusiveGroup only supports \l Action as child items, we need to manually assign the \c exclusiveGroup
+ property for other objects.
+
+ \code
+ ExclusiveGroup { id: textAlignmentGroup }
+
+ Menu {
+ MenuItem {
+ text: "Alignt Left"
+ checkable: true
+ exclusiveGroup: textAlignmentGroup
+ }
+ MenuItem {
+ text: "Alignt Right"
+ checkable: true
+ exclusiveGroup: textAlignmentGroup
+ }
+ MenuItem {
+ text: "Center"
+ checkable: true
+ exclusiveGroup: textAlignmentGroup
+ }
+ MenuItem {
+ text: "Justify"
+ checkable: true
+ exclusiveGroup: textAlignmentGroup
+ }
+ }
+ \endcode
+
+ \section1 Adding support to ExclusiveGroup
+
+ It is possible to add support for \l ExclusiveGroup for an object, or control. It should have a \c checked
+ property, and either a \c checkedChanged, \c toggled(), or \c toggled(bool) signal. It also needs
+ to be bound with \l ExclusiveGroup::bindCheckable(object) when its \l ExclusiveGroup ty[ped property is set.
+
+ \code
+ Item {
+ id: myItem
+
+ property bool checked: false
+ property ExclusiveGroup exclusiveGroup: null
+
+ onExclusiveGroupChanged: {
+ if (exclusiveGroup)
+ exclusiveGroup.bindCheckable(myItem)
+ }
+ }
+ \endcode
+
+ The example above shows the minimum necessary to add \l ExclusiveGroup support to any item.
+*/
+
+/*!
+ \qmlproperty object ExclusiveGroup::current
+
+ The currently selected object. Defaults to the first checked object bound to the \l ExclusiveGroup.
+ If there is none, then it defaults to \c null.
+*/
+
+/*!
+ \qmlmethod void ExclusiveGroup::bindCheckable(object)
+
+ Register \c object to the exclusive group.
+
+ You should only need to call this function when creating a component you want to be compatible with \c ExclusiveGroup.
+
+ \sa ExclusiveGroup::unbindCheckable(object)
+*/
+
+/*!
+ \qmlmethod void ExclusiveGroup::unbindCheckable(object)
+
+ Unregister \c object from the exclusive group.
+
+ You should only need to call this function when creating a component you want to be compatible with \c ExclusiveGroup.
+
+ \sa ExclusiveGroup::bindCheckable(object)
+*/
+
+QQuickExclusiveGroup::QQuickExclusiveGroup(QObject *parent)
+ : QObject(parent), m_current(0)
+{
+ int index = metaObject()->indexOfMethod("updateCurrent()");
+ m_updateCurrentMethod = metaObject()->method(index);
+}
+
+QQmlListProperty<QQuickAction> QQuickExclusiveGroup::actions()
+{
+ return QQmlListProperty<QQuickAction>(this, 0, &QQuickExclusiveGroup::append_actions, 0, 0, 0);
+}
+
+void QQuickExclusiveGroup::append_actions(QQmlListProperty<QQuickAction> *list, QQuickAction *action)
+{
+ if (QQuickExclusiveGroup *eg = qobject_cast<QQuickExclusiveGroup *>(list->object))
+ action->setExclusiveGroup(eg);
+}
+
+void QQuickExclusiveGroup::setCurrent(QObject * o)
+{
+ if (m_current == o)
+ return;
+
+ if (m_current)
+ m_current->setProperty(CHECKED_PROPERTY, QVariant(false));
+ m_current = o;
+ if (m_current)
+ m_current->setProperty(CHECKED_PROPERTY, QVariant(true));
+ emit currentChanged();
+}
+
+void QQuickExclusiveGroup::updateCurrent()
+{
+ QObject *checkable = sender();
+ if (isChecked(checkable))
+ setCurrent(checkable);
+}
+
+void QQuickExclusiveGroup::bindCheckable(QObject *o)
+{
+ for (const char **signalName = checkableSignals; *signalName; signalName++) {
+ int signalIndex = o->metaObject()->indexOfSignal(*signalName);
+ if (signalIndex != -1) {
+ QMetaMethod signalMethod = o->metaObject()->method(signalIndex);
+ connect(o, signalMethod, this, m_updateCurrentMethod, Qt::UniqueConnection);
+ connect(o, SIGNAL(destroyed(QObject*)), this, SLOT(unbindCheckable(QObject*)), Qt::UniqueConnection);
+ if (!m_current && isChecked(o))
+ setCurrent(o);
+ return;
+ }
+ }
+
+ qWarning() << "QQuickExclusiveGroup::bindCheckable(): Cannot bind to" << o;
+}
+
+void QQuickExclusiveGroup::unbindCheckable(QObject *o)
+{
+ if (m_current == o)
+ setCurrent(0);
+ for (const char **signalName = checkableSignals; *signalName; signalName++) {
+ int signalIndex = o->metaObject()->indexOfSignal(*signalName);
+ if (signalIndex != -1) {
+ QMetaMethod signalMethod = o->metaObject()->method(signalIndex);
+ if (disconnect(o, signalMethod, this, m_updateCurrentMethod)) {
+ disconnect(o, SIGNAL(destroyed(QObject*)), this, SLOT(unbindCheckable(QObject*)));
+ break;
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE