aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/QMenuModel/plugin.cpp5
-rw-r--r--src/common/converter.cpp53
-rw-r--r--src/common/converter.h5
-rw-r--r--src/common/qdbusactiongroup.cpp121
-rw-r--r--src/common/qdbusactiongroup.h21
-rw-r--r--src/common/qmenumodel.cpp2
-rw-r--r--src/common/qstateaction.cpp52
-rw-r--r--src/common/qstateaction.h23
-rw-r--r--tests/client/CMakeLists.txt22
-rw-r--r--tests/client/actiongrouptest.cpp7
-rw-r--r--tests/client/convertertest.cpp91
11 files changed, 277 insertions, 125 deletions
diff --git a/src/QMenuModel/plugin.cpp b/src/QMenuModel/plugin.cpp
index fbd943c..494dd2c 100644
--- a/src/QMenuModel/plugin.cpp
+++ b/src/QMenuModel/plugin.cpp
@@ -30,9 +30,12 @@ void QMenuModelQmlPlugin::registerTypes(const char *uri)
{
qmlRegisterUncreatableType<QMenuModel>(uri, 0, 1, "QMenuModel",
"QMenuModel is a interface");
+ qmlRegisterUncreatableType<QStateAction>(uri, 0, 1, "QStateAction",
+ "QStateAction must be created by QDBusActionGroup::action");
+
qmlRegisterType<QDBusMenuModel>(uri, 0, 1, "QDBusMenuModel");
qmlRegisterType<QDBusActionGroup>(uri, 0, 1, "QDBusActionGroup");
- qmlRegisterType<QStateAction>(uri, 0, 1, "QStateAction");
+
}
Q_EXPORT_PLUGIN2(qmenumodel, QMenuModelQmlPlugin)
diff --git a/src/common/converter.cpp b/src/common/converter.cpp
index c5cdade..54d4665 100644
--- a/src/common/converter.cpp
+++ b/src/common/converter.cpp
@@ -3,7 +3,7 @@
#include <QDebug>
/*! \internal */
-QVariant Converter::toGVariant(GVariant *value)
+QVariant Converter::toQVariant(GVariant *value)
{
QVariant result;
if (value == NULL) {
@@ -59,3 +59,54 @@ QVariant Converter::toGVariant(GVariant *value)
return result;
}
+
+GVariant* Converter::toGVariant(const QString &typeName, const QVariant &value)
+{
+ if (typeName == "uchar") {
+ return g_variant_new_byte(value.value<uchar>());
+ } else if (typeName == "short") {
+ return g_variant_new_int16(value.value<short>());
+ } else if (typeName == "ushort") {
+ return g_variant_new_uint16(value.value<ushort>());
+ } else if (typeName == "long") {
+ return g_variant_new_int64(value.value<long>());
+ } else if (typeName == "ulong") {
+ return g_variant_new_uint64(value.value<ulong>());
+ } else {
+ qWarning() << "QVariant type not supported:" << typeName;
+ }
+
+ return NULL;
+}
+
+GVariant* Converter::toGVariant(const QVariant &value)
+{
+ GVariant *result = NULL;
+ if (value.isNull() || !value.isValid())
+ return result;
+
+ switch(value.type()) {
+ case QVariant::Bool:
+ result = g_variant_new_boolean(value.toBool());
+ break;
+ case QVariant::ByteArray:
+ result = g_variant_new_bytestring(value.toByteArray());
+ break;
+ case QVariant::Double:
+ result = g_variant_new_double(value.toDouble());
+ break;
+ case QVariant::Int:
+ result = g_variant_new_int32(value.toInt());
+ break;
+ case QVariant::String:
+ result = g_variant_new_string(value.toString().toLatin1());
+ break;
+ case QVariant::UInt:
+ result = g_variant_new_uint32(value.toUInt());
+ break;
+ default:
+ result = toGVariant(value.typeName(), value);
+ }
+
+ return result;
+}
diff --git a/src/common/converter.h b/src/common/converter.h
index 6ad4b2c..3029b0d 100644
--- a/src/common/converter.h
+++ b/src/common/converter.h
@@ -26,11 +26,14 @@
class Converter
{
public:
- static QVariant toGVariant(GVariant *value);
+ static QVariant toQVariant(GVariant *value);
+ static GVariant* toGVariant(const QVariant &value);
private:
Converter();
Converter(const Converter &other);
+
+ static GVariant* toGVariant(const QString &typeName, const QVariant &value);
};
#endif
diff --git a/src/common/qdbusactiongroup.cpp b/src/common/qdbusactiongroup.cpp
index b6f52f5..305e12e 100644
--- a/src/common/qdbusactiongroup.cpp
+++ b/src/common/qdbusactiongroup.cpp
@@ -73,15 +73,24 @@ QStateAction *QDBusActionGroup::action(const QString &name)
{
QStateAction *act = actionImpl(name);
if (act == 0) {
- return addAction(name.toLatin1(), true);
+ return new QStateAction(this, name);
} else {
return act;
}
}
+bool QDBusActionGroup::hasAction(const QString &actionName)
+{
+ if (m_actionGroup) {
+ return g_action_group_has_action(m_actionGroup, actionName.toLatin1());
+ } else {
+ return false;
+ }
+}
+
QStateAction *QDBusActionGroup::actionImpl(const QString &name)
{
- Q_FOREACH(QStateAction *act, m_actions) {
+ Q_FOREACH(QStateAction *act, this->findChildren<QStateAction*>()) {
if (act->text() == name) {
return act;
}
@@ -89,19 +98,10 @@ QStateAction *QDBusActionGroup::actionImpl(const QString &name)
return 0;
}
-/*!
- \qmlproperty int QDBusActionGroup::count
- This property holds the number of actions inside of \l QDBusActionGroup
-*/
-int QDBusActionGroup::count() const
-{
- return m_actions.count();
-}
-
/*! \internal */
void QDBusActionGroup::serviceVanish(GDBusConnection *)
{
- clear();
+ setActionGroup(NULL);
}
/*! \internal */
@@ -147,8 +147,8 @@ void QDBusActionGroup::setActionGroup(GDBusActionGroup *ag)
g_signal_handler_disconnect(m_actionGroup, m_signalActionAddId);
g_signal_handler_disconnect(m_actionGroup, m_signalActionRemovedId);
g_signal_handler_disconnect(m_actionGroup, m_signalStateChangedId);
- m_signalActionAddId = m_signalActionRemovedId = m_signalStateChangedId = 0;
- g_object_unref(m_actionGroup);
+ m_signalActionAddId = m_signalActionRemovedId = m_signalStateChangedId = 0;
+ clear();
}
m_actionGroup = reinterpret_cast<GActionGroup*>(ag);
@@ -169,93 +169,32 @@ void QDBusActionGroup::setActionGroup(GDBusActionGroup *ag)
G_CALLBACK(QDBusActionGroup::onActionStateChanged),
this);
- gchar **actionNames = g_action_group_list_actions(m_actionGroup);
- for(int i=0; actionNames[i] != NULL; i++) {
- addAction(actionNames[i], true);
+ gchar **actions = g_action_group_list_actions(m_actionGroup);
+ for(int i=0; i < g_strv_length(actions); i++) {
+ Q_EMIT actionAppear(actions[i]);
}
- g_strfreev(actionNames);
+ g_strfreev(actions);
}
}
/*! \internal */
-QStateAction *QDBusActionGroup::addAction(const char *actionName, bool create)
-{
- bool isNew = false;
- QStateAction *act = actionImpl(actionName);
- if (act == 0) {
- if (create) {
- act = new QStateAction(actionName, this);
- isNew = true;
- } else {
- return 0;
- }
- }
-
- if (g_action_group_has_action(m_actionGroup, actionName)) {
- act->setEnabled(g_action_group_get_action_enabled(m_actionGroup, actionName));
-
- GVariant *actState = g_action_group_get_action_state(m_actionGroup, actionName);
- if (actState) {
- act->setState(Converter::toGVariant(actState));
- }
- act->setValid(true);
- } else {
- act->setValid(false);
- }
-
- if (isNew) {
- QObject::connect(act, SIGNAL(triggered()), this, SLOT(onActionTriggered()));
- m_actions.insert(act);
- Q_EMIT countChanged(m_actions.count());
- }
- return act;
-}
-
-/*! \internal */
-void QDBusActionGroup::onActionTriggered()
-{
- QStateAction *act = qobject_cast<QStateAction*>(QObject::sender());
- if (act->isValid()) {
- g_action_group_activate_action(m_actionGroup, act->text().toLatin1(), NULL);
- }
-}
-
-/*! \internal */
-void QDBusActionGroup::removeAction(const char *actionName, bool erase)
+void QDBusActionGroup::clear()
{
- Q_FOREACH(QStateAction *act, m_actions) {
- if (act->text() == actionName) {
- if (erase) {
- m_actions.remove(act);
- delete act;
- } else {
- act->setValid(false);
- }
- break;
- }
+ Q_FOREACH(QStateAction *act, this->findChildren<QStateAction*>()) {
+ Q_EMIT actionVanish(act->text());
}
-}
-/*! \internal */
-void QDBusActionGroup::updateAction(const char *actionName, GVariant *state)
-{
- QStateAction *action = this->action(actionName);
- if ((action != NULL) && (state != NULL)) {
- action->setState(Converter::toGVariant(state));
+ if (m_actionGroup != NULL) {
+ g_object_unref(m_actionGroup);
+ m_actionGroup = NULL;
}
}
/*! \internal */
-void QDBusActionGroup::clear()
+void QDBusActionGroup::updateActionState(const QString &actionName, const QVariant &state)
{
- Q_FOREACH(QAction *act, m_actions) {
- delete act;
- }
- m_actions.clear();
-
if (m_actionGroup != NULL) {
- g_object_unref(m_actionGroup);
- m_actionGroup = NULL;
+ g_action_group_activate_action(m_actionGroup, actionName.toLatin1(), Converter::toGVariant(state));
}
}
@@ -263,19 +202,19 @@ void QDBusActionGroup::clear()
void QDBusActionGroup::onActionAdded(GDBusActionGroup *, gchar *actionName, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- self->addAction(actionName, true);
+ Q_EMIT self->actionAppear(actionName);
}
/*! \internal */
void QDBusActionGroup::onActionRemoved(GDBusActionGroup *, gchar *actionName, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- self->removeAction(actionName, false);
+ Q_EMIT self->actionVanish(actionName);
}
/*! \internal */
-void QDBusActionGroup::onActionStateChanged(GDBusActionGroup *ag, gchar *actionName, GVariant *value, gpointer data)
+void QDBusActionGroup::onActionStateChanged(GDBusActionGroup *, gchar *actionName, GVariant *value, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- self->updateAction(actionName, value);
+ Q_EMIT self->actionStateChanged(actionName, Converter::toQVariant(value));
}
diff --git a/src/common/qdbusactiongroup.h b/src/common/qdbusactiongroup.h
index f2b2033..723094c 100644
--- a/src/common/qdbusactiongroup.h
+++ b/src/common/qdbusactiongroup.h
@@ -35,13 +35,13 @@ class QDBusActionGroup : public QObject, public QDBusObject
Q_PROPERTY(QString busName READ busName WRITE setBusName NOTIFY busNameChanged)
Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath NOTIFY objectPathChanged)
Q_PROPERTY(int status READ status NOTIFY statusChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
QDBusActionGroup(QObject *parent=0);
~QDBusActionGroup();
- int count() const;
+ void updateActionState(const QString &actionName, const QVariant &state);
+ bool hasAction(const QString &actionName);
Q_INVOKABLE QStateAction *action(const QString &actionName);
@@ -50,25 +50,20 @@ Q_SIGNALS:
void busNameChanged(const QString &busNameChanged);
void objectPathChanged(const QString &objectPath);
void statusChanged(ConnectionStatus status);
- void countChanged(int count);
-
+ void actionAppear(const QString &actionName);
+ void actionVanish(const QString &actionName);
+ void actionStateChanged(const QString &actionName, QVariant state);
public Q_SLOTS:
void start();
void stop();
-
protected:
virtual void serviceAppear(GDBusConnection *connection);
virtual void serviceVanish(GDBusConnection *connection);
-
-private Q_SLOTS:
- void onActionTriggered();
-
private:
GActionGroup *m_actionGroup;
- QSet<QStateAction*> m_actions;
int m_signalActionAddId;
int m_signalActionRemovedId;
int m_signalStateChangedId;
@@ -77,12 +72,10 @@ private:
void setIntBusType(int busType);
void setActionGroup(GDBusActionGroup *ag);
- QStateAction *addAction(const char *actionName, bool create);
- void removeAction(const char *actionName, bool erase);
- void updateAction(const char *actionName, GVariant *state);
- void clear();
QStateAction *actionImpl(const QString &actionName);
+ void clear();
+
// glib slots
static void onActionAdded(GDBusActionGroup *ag, gchar *actionName, gpointer data);
static void onActionRemoved(GDBusActionGroup *ag, gchar *actionName, gpointer data);
diff --git a/src/common/qmenumodel.cpp b/src/common/qmenumodel.cpp
index f8d71ba..cc760c1 100644
--- a/src/common/qmenumodel.cpp
+++ b/src/common/qmenumodel.cpp
@@ -202,7 +202,7 @@ QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const
while (g_menu_attribute_iter_get_next (iter, &attrName, &value)) {
if (strncmp("x-", attrName, 2) == 0) {
extra.insert(parseExtraPropertyName(attrName),
- Converter::toGVariant(value));
+ Converter::toQVariant(value));
}
}
diff --git a/src/common/qstateaction.cpp b/src/common/qstateaction.cpp
index 8e3c7c3..1369bfc 100644
--- a/src/common/qstateaction.cpp
+++ b/src/common/qstateaction.cpp
@@ -19,6 +19,8 @@
#include "qstateaction.h"
+#include "qdbusactiongroup.h"
+
/*!
\qmlclass QStateAction
\inherits QAction
@@ -44,9 +46,20 @@
*/
/*! \internal */
-QStateAction::QStateAction(const QString &text, QObject *parent)
- :QAction(text, parent)
+QStateAction::QStateAction(QDBusActionGroup *group, const QString &name)
+ : QAction(name, group),
+ m_group(group)
{
+ QObject::connect(this, SIGNAL(triggered()), this, SLOT(onTriggered()));
+
+ // This keep the code clean
+ // But maybe we need move the action state control to QActionGroup to optimizations
+ QObject::connect(m_group, SIGNAL(actionAppear(QString)),
+ this, SLOT(onActionAppear(QString)));
+ QObject::connect(m_group, SIGNAL(actionVanish(QString)),
+ this, SLOT(onActionVanish(QString)));
+ QObject::connect(m_group, SIGNAL(actionStateUpdated(QString,QVariant)),
+ this, SLOT(onActionStateUpdate(QString,QVariant)));
}
/*!
@@ -68,6 +81,11 @@ bool QStateAction::isValid() const
return m_valid;
}
+void QStateAction::updateState(const QVariant &state)
+{
+ m_group->updateActionState(text(), state);
+}
+
/*! \internal */
void QStateAction::setValid(bool valid)
{
@@ -85,3 +103,33 @@ void QStateAction::setState(const QVariant &state)
Q_EMIT stateChanged(m_state);
}
}
+
+/*! \internal */
+void QStateAction::onTriggered()
+{
+ updateState(QVariant());
+}
+
+/*! \internal */
+void QStateAction::onActionAppear(const QString &actionName)
+{
+ if (text() == actionName) {
+ setValid(true);
+ }
+}
+
+/*! \internal */
+void QStateAction::onActionVanish(const QString &actionName)
+{
+ if (text() == actionName) {
+ setValid(false);
+ }
+}
+
+/*! \internal */
+void QStateAction::onActionStateUpdate(const QString &actionName, const QVariant &state)
+{
+ if (text() == actionName) {
+ setState(state);
+ }
+}
diff --git a/src/common/qstateaction.h b/src/common/qstateaction.h
index 4019c64..c6bdcea 100644
--- a/src/common/qstateaction.h
+++ b/src/common/qstateaction.h
@@ -23,28 +23,37 @@
#include <QAction>
#include <QVariant>
+class QDBusActionGroup;
+
class QStateAction : public QAction
{
Q_OBJECT
Q_PROPERTY(QVariant state READ state WRITE setState NOTIFY stateChanged)
Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
-public:
- QStateAction(const QString &text="", QObject *parent=0);
-
- QVariant state() const;
- void setState(const QVariant &state);
-
+public:
+ QVariant state() const;
bool isValid() const;
+ Q_INVOKABLE void updateState(const QVariant &state);
+
Q_SIGNALS:
void stateChanged(QVariant state);
void validChanged(bool valid);
+private Q_SLOTS:
+ void onActionAppear(const QString &actionName);
+ void onActionVanish(const QString &actionName);
+ void onActionStateUpdate(const QString &actionNane, const QVariant &state);
+ void onTriggered();
+
private:
- QVariant m_state;
+ QDBusActionGroup *m_group;
+ QVariant m_state;
bool m_valid;
+ QStateAction(QDBusActionGroup *group, const QString &name);
void setValid(bool valid);
+ void setState(const QVariant &state);
friend class QDBusActionGroup;
};
diff --git a/tests/client/CMakeLists.txt b/tests/client/CMakeLists.txt
index 473ebcd..c427f54 100644
--- a/tests/client/CMakeLists.txt
+++ b/tests/client/CMakeLists.txt
@@ -24,6 +24,27 @@ macro(declare_test testname)
endmacro(declare_test testname)
+macro(declare_simple_test testname)
+ set(TEST_MOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${testname}.moc)
+ qt4_generate_moc(${testname}.cpp ${TEST_MOC_FILE})
+
+ add_executable(${testname} ${testname}.cpp ${TEST_MOC_FILE})
+ target_link_libraries(${testname}
+ qmenumodelcommon
+ ${QT_QTTEST_LIBRARY}
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTGUI_LIBRARY}
+ ${QT_QTDBUS_LIBRARY}
+ ${GLIB_LDFLAGS}
+ ${GIO_LDFLAGS})
+
+ add_test(${testname}
+ ${CMAKE_CURRENT_BINARY_DIR}/${testname})
+
+ set_tests_properties(${testname} PROPERTIES
+ TIMEOUT ${CTEST_TESTING_TIMEOUT})
+endmacro(declare_simple_test testname)
+
include_directories(${qmenumodelcommon_SOURCE_DIR}
${dbusmenuscript_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
@@ -45,3 +66,4 @@ declare_test(servicetest)
declare_test(menuchangestest)
declare_test(modeltest)
declare_test(actiongrouptest)
+declare_simple_test(convertertest)
diff --git a/tests/client/actiongrouptest.cpp b/tests/client/actiongrouptest.cpp
index fa2dca5..c77c3d5 100644
--- a/tests/client/actiongrouptest.cpp
+++ b/tests/client/actiongrouptest.cpp
@@ -91,13 +91,11 @@ private Q_SLOTS:
m_model.start();
m_actionGroup.start();
QCOMPARE(m_actionGroup.status(), QDBusObject::Connecting);
- QCOMPARE(m_actionGroup.count(), 0);
// Make menu available
m_script.publishMenu();
QCOMPARE(m_actionGroup.status(), QDBusObject::Connected);
- QCOMPARE(m_actionGroup.count(), 0);
}
/*
@@ -108,7 +106,6 @@ private Q_SLOTS:
{
m_model.start();
m_actionGroup.start();
- QCOMPARE(m_actionGroup.count(), 0);
// Make menu available
m_script.publishMenu();
@@ -116,12 +113,10 @@ private Q_SLOTS:
// Append menus
m_script.walk(2);
- QCOMPARE(m_actionGroup.count(), 2);
// Remove menu from dbus
m_script.unpublishMenu();
QCOMPARE(m_actionGroup.status(), QDBusObject::Connecting);
- QCOMPARE(m_actionGroup.count(), 0);
m_actionGroup.stop();
QCOMPARE(m_actionGroup.status(), QDBusObject::Disconnected);
@@ -165,7 +160,6 @@ private Q_SLOTS:
// Make menu available and append 2 menus
m_script.publishMenu();
m_script.walk(2);
- QCOMPARE(m_actionGroup.count(), 2);
// Get Action
QStateAction *act = m_actionGroup.action(QString("Menu1Act"));
@@ -174,7 +168,6 @@ private Q_SLOTS:
// Remove 1 menu
m_script.walk(1);
- QCOMPARE(m_actionGroup.count(), 2);
//Check if action is invalid
QVERIFY(!act->isValid());
diff --git a/tests/client/convertertest.cpp b/tests/client/convertertest.cpp
new file mode 100644
index 0000000..496b62a
--- /dev/null
+++ b/tests/client/convertertest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Renato Araujo Oliveira Filho <renato@canonical.com>
+ */
+
+#include "converter.h"
+
+#include <QObject>
+#include <QtTestGui>
+#include <QDebug>
+
+class ConverterTest : public QObject
+{
+ Q_OBJECT
+
+private:
+ bool compare(const QVariant &qv, const GVariantType *type)
+ {
+ bool result;
+ GVariant *gv = Converter::toGVariant(qv);
+ result = g_variant_type_equal(g_variant_get_type(gv), type);
+ if (!result) {
+ qWarning() << "types are different: QVariant:" << qv.typeName()
+ << "Result:" << (const char*) g_variant_get_type(gv)
+ << "Expected:"<< (const char*) type;
+ }
+ g_variant_unref(gv);
+ return result;
+ }
+
+private Q_SLOTS:
+
+
+ /*
+ * Test converter QVariant to GVariant
+ */
+ void testToGVariant()
+ {
+ // Boolean
+ QVERIFY(compare(QVariant(true), G_VARIANT_TYPE_BOOLEAN));
+
+ // Byte
+ QVERIFY(compare(QVariant::fromValue<uchar>(42), G_VARIANT_TYPE_BYTE));
+
+ // Int16
+ QVERIFY(compare(QVariant::fromValue<short>(-42), G_VARIANT_TYPE_INT16));
+
+ // UInt16
+ QVERIFY(compare(QVariant::fromValue<ushort>(-42), G_VARIANT_TYPE_UINT16));
+
+ // Int32
+ QVERIFY(compare(QVariant(-42), G_VARIANT_TYPE_INT32));
+
+ // UInt32
+ QVERIFY(compare(QVariant((uint)42), G_VARIANT_TYPE_UINT32));
+
+ // Int64
+ QVERIFY(compare(QVariant::fromValue<long>(-42), G_VARIANT_TYPE_INT64));
+
+ // UInt64
+ QVERIFY(compare(QVariant::fromValue<ulong>(42), G_VARIANT_TYPE_UINT64));
+
+ // Double
+ QVERIFY(compare(QVariant((double)42.42), G_VARIANT_TYPE_DOUBLE));
+
+ // String
+ QVERIFY(compare(QVariant(QString("42")), G_VARIANT_TYPE_STRING));
+
+ // ByteArray
+ QVERIFY(compare(QVariant(QByteArray("42")), G_VARIANT_TYPE_BYTESTRING));
+ }
+
+};
+
+QTEST_MAIN(ConverterTest)
+
+#include "convertertest.moc"