diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | libcontextprovider/context-provide/Makefile.am | 4 | ||||
-rw-r--r-- | libcontextprovider/context-provide/commandwatcher.cpp | 23 | ||||
-rw-r--r-- | libcontextsubscriber/cli/Makefile.am | 4 | ||||
-rw-r--r-- | libcontextsubscriber/cli/commandwatcher.cpp | 198 | ||||
-rw-r--r-- | libcontextsubscriber/cli/commandwatcher.h | 5 | ||||
-rw-r--r-- | libcontextsubscriber/cli/context-listen.cpp | 11 | ||||
-rw-r--r-- | libcontextsubscriber/cli/propertylistener.cpp | 37 | ||||
-rw-r--r-- | libcontextsubscriber/cli/propertylistener.h | 5 | ||||
-rwxr-xr-x | libcontextsubscriber/customer-tests/commander/commander_nonexistent.py | 2 | ||||
-rwxr-xr-x | libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py | 4 | ||||
-rwxr-xr-x | libcontextsubscriber/customer-tests/subscription/multiprovider2.py | 2 | ||||
-rwxr-xr-x | libcontextsubscriber/customer-tests/subscription/subscription.py | 42 | ||||
-rw-r--r-- | libcontextsubscriber/src/contextkitplugin.cpp | 47 | ||||
-rw-r--r-- | libcontextsubscriber/src/propertyhandle.cpp | 3 | ||||
-rw-r--r-- | python/ContextKit/cltool.py | 2 |
17 files changed, 226 insertions, 167 deletions
diff --git a/configure.ac b/configure.ac index c2a14908..d62c6f68 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,7 @@ PKG_CHECK_MODULES_SUBST([QtTest], [QtTest]) PKG_CHECK_MODULES_SUBST([QtCore], [QtCore]) PKG_CHECK_MODULES_SUBST([QtDBus], [QtDBus]) PKG_CHECK_MODULES_SUBST([QtXml], [QtXml]) +PKG_CHECK_MODULES_SUBST([QJson], [QJson]) # only for compiling c code PKG_CHECK_MODULES_SUBST([DBUS], [dbus-1]) PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.12.0]) diff --git a/debian/control b/debian/control index 76418442..5111c070 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 5), libcdb-dev, libglib2.0-dev (>= 2.12.0), libdbus-1-dev, + libqjson-dev, xsltproc, doxygen XS-Python-Version: all @@ -94,7 +95,7 @@ Description: Python bindings for ContextKit APIs Package: contextkit-utils Section: utils Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, libqjson Description: Command line utilities for ContextKit This package contains the context-provide and context-listen tools. You can use context-provide to quickly provide context diff --git a/libcontextprovider/context-provide/Makefile.am b/libcontextprovider/context-provide/Makefile.am index 87a4a22c..2eca452c 100644 --- a/libcontextprovider/context-provide/Makefile.am +++ b/libcontextprovider/context-provide/Makefile.am @@ -4,9 +4,9 @@ context_provide_SOURCES = context-provide.cpp \ commandwatcher.cpp commandwatcher.h propertyproxy.h \ propertyproxy.cpp -AM_CXXFLAGS = $(QtCore_CFLAGS) $(QtDBus_CFLAGS) \ +AM_CXXFLAGS = $(QtCore_CFLAGS) $(QtDBus_CFLAGS) $(QJson_CFLAGS) \ '-DCONTEXT_LOG_MODULE_NAME="context-provide"' -LIBS += $(QtCore_LIBS) +LIBS += $(QtCore_LIBS) $(QJson_LIBS) # library dependency hack for seamless make AM_CXXFLAGS += -I$(srcdir)/../src \ diff --git a/libcontextprovider/context-provide/commandwatcher.cpp b/libcontextprovider/context-provide/commandwatcher.cpp index 23320422..df96a2f2 100644 --- a/libcontextprovider/context-provide/commandwatcher.cpp +++ b/libcontextprovider/context-provide/commandwatcher.cpp @@ -38,6 +38,7 @@ #include <QMap> #include <QDir> #include <QSet> +#include <qjson/parser.h> const QString CommandWatcher::commanderBusName = "org.freedesktop.ContextKit.Commander"; @@ -179,9 +180,9 @@ void CommandWatcher::addCommand(const QStringList& args) QString keyType = unquote(args.at(0)).toUpper(); const QString keyName = unquote(args.at(1)); - if (keyType != "INT" && keyType != "STRING" && + if (keyType != "ANY" && keyType != "INT" && keyType != "STRING" && keyType != "DOUBLE" && keyType != "TRUTH" && keyType != "BOOL") { - qDebug() << "ERROR: Unknown type (has to be: INT, STRING, DOUBLE, BOOL or TRUTH)"; + qDebug() << "ERROR: Unknown type (has to be: COMPLEX, INT, STRING, DOUBLE, BOOL or TRUTH)"; return; } if (keyType == "BOOL") keyType = "TRUTH"; @@ -332,7 +333,7 @@ void CommandWatcher::dumpCommand(const QStringList &args) void CommandWatcher::setCommand(const QString& command) { const QString keyName = unquote(command.left(command.indexOf('=')).trimmed()); - const QString value = unquote(command.mid(command.indexOf('=')+1).trimmed()); + QString value = command.mid(command.indexOf('=')+1).trimmed(); if (! types.contains(keyName)) { qDebug() << "ERROR: key" << keyName << "not known/added"; @@ -343,6 +344,9 @@ void CommandWatcher::setCommand(const QString& command) const QString keyType = types.value(keyName); QVariant v; + if (keyType != "ANY") + value = unquote(value); + if (keyType == "INT") v = QVariant(value.toInt()); else if (keyType == "STRING") @@ -354,9 +358,20 @@ void CommandWatcher::setCommand(const QString& command) v = QVariant(true); else v = QVariant(false); + } else if (keyType == "ANY") { + QJson::Parser parser; + bool ok; + + v = parser.parse(value.toUtf8(), &ok); + if (!ok) { + qDebug() << "An error occurred during parsing"; + return; + } } - out << "Setting key: " << keyName << " to value: " << v.toString() << endl; + QString vstr; + QDebug(&vstr) << v; + out << "Setting key: " << keyName << " to value: " << vstr << endl; out.flush(); prop->setValue(v); } diff --git a/libcontextsubscriber/cli/Makefile.am b/libcontextsubscriber/cli/Makefile.am index 21f6b543..acaabdde 100644 --- a/libcontextsubscriber/cli/Makefile.am +++ b/libcontextsubscriber/cli/Makefile.am @@ -3,9 +3,9 @@ context_listen_SOURCES = context-listen.cpp \ propertylistener.h propertylistener.cpp commandwatcher.h \ commandwatcher.cpp -AM_CXXFLAGS = $(QtCore_CFLAGS) $(QtDBus_CFLAGS) \ +AM_CXXFLAGS = $(QtCore_CFLAGS) $(QtDBus_CFLAGS) $(QJson_CFLAGS) \ '-DCONTEXT_LOG_MODULE_NAME="context-listen"' -LIBS += $(QtCore_LIBS) +LIBS += $(QtCore_LIBS) $(QJson_LIBS) # library dependency hack for seamless make in cli/ AM_CXXFLAGS += -I$(srcdir)/../src \ diff --git a/libcontextsubscriber/cli/commandwatcher.cpp b/libcontextsubscriber/cli/commandwatcher.cpp index aa761c9d..d4ff45d6 100644 --- a/libcontextsubscriber/cli/commandwatcher.cpp +++ b/libcontextsubscriber/cli/commandwatcher.cpp @@ -35,7 +35,7 @@ #include <errno.h> #include <QMap> -CommandWatcher::CommandWatcher(int commandfd, QMap<QString, ContextProperty*> *properties, QObject *parent) : +CommandWatcher::CommandWatcher(int commandfd, QMap<QString, PropertyListener*> *properties, QObject *parent) : QObject(parent), commandfd(commandfd), properties(properties) { commandNotifier = new QSocketNotifier(commandfd, QSocketNotifier::Read, this); @@ -83,7 +83,6 @@ void CommandWatcher::help() qDebug() << " plugin KEY - get the info()->plugin for a key"; qDebug() << " constructionstring KEY - get the info()->constructionstring for a key"; qDebug() << " providers KEY - get the info()->providers for a key"; - qDebug() << " flush - write FLUSHED to stderr and stdout"; qDebug() << "Any prefix of a command can be used as an abbreviation"; } @@ -91,128 +90,107 @@ void CommandWatcher::interpret(const QString& command) const { QTextStream out(stdout); QTextStream err(stderr); - if (command == "") { - help(); - } else { - QStringList args = command.split(" "); - QString commandName = args[0]; - args.pop_front(); - - if (args.size() == 0 && !QString("flush").startsWith(commandName)) { - help(); - return; - } + QStringList args = command.split(" "); + QString commandName = args[0]; + args.pop_front(); - if (QString("new").startsWith(commandName)) { - foreach (QString key, args) - if (properties->contains(key)) - qDebug() << "key already exists: " << key; - else { - properties->insert(key, new ContextProperty(key, QCoreApplication::instance())); - new PropertyListener(properties->value(key)); - } - } else if (QString("delete").startsWith(commandName)) { - foreach (QString key, args) - if (properties->contains(key)) - delete properties->take(key); - else - qDebug() << "no such key:" << key; - } else if (QString("subscribe").startsWith(commandName)) { - foreach (QString key, args) - if (properties->contains(key)) - properties->value(key)->subscribe(); - else - qDebug() << "no such key:" << key; - } else if (QString("waitforsubscription").startsWith(commandName)) { - foreach (QString key, args) - if (properties->contains(key)) { - properties->value(key)->waitForSubscription(); - out << "wait finished for " << key << endl; - } else - qDebug() << "no such key:" << key; - } else if (QString("unsubscribe").startsWith(commandName)) { - foreach (QString key, args) - if (properties->contains(key)) - properties->value(key)->unsubscribe(); - else - qDebug() << "no such key:" << key; - } else if (QString("value").startsWith(commandName)) { - QString key = args[0]; - if (properties->contains(key)) { - QVariant value; - if (args.size() > 1) { - value = properties->value(key)->value(args[1]); - } else { - value = properties->value(key)->value(); - } - if (value.isNull()) - out << "value is Unknown" << endl; - else - out << "value: " << value.typeName() << ":" << value.toString() << endl; - } else - qDebug() << "no such key:" << key; - } else if (QString("key").startsWith(commandName)) { - QString key = args[0]; - if (properties->contains(key)) - out << "key: " << properties->value(key)->key() << endl; - else - qDebug() << "no such key:" << key; - } else if (QString("ikey").startsWith(commandName)) { - QString key = args[0]; + if (QString("new").startsWith(commandName)) { + foreach (QString key, args) if (properties->contains(key)) - out << "ikey: " << properties->value(key)->info()->key() << endl; + qDebug() << "key already exists: " << key; else - qDebug() << "no such key:" << key; - } else if (QString("man").startsWith(commandName)) { - QString key = args[0]; + properties->insert(key, new PropertyListener(key)); + } else if (QString("delete").startsWith(commandName)) { + foreach (QString key, args) if (properties->contains(key)) - out << "man: " << properties->value(key)->info()->doc() << endl; + delete properties->take(key); else qDebug() << "no such key:" << key; - } else if (QString("type").startsWith(commandName)) { - QString key = args[0]; + } else if (QString("subscribe").startsWith(commandName)) { + foreach (QString key, args) if (properties->contains(key)) - out << "type: " << properties->value(key)->info()->type() << endl; + properties->value(key)->prop->subscribe(); else qDebug() << "no such key:" << key; - } else if (QString("plugin").startsWith(commandName)) { - QString key = args[0]; + } else if (QString("waitforsubscription").startsWith(commandName)) { + foreach (QString key, args) if (properties->contains(key)) { - QList<ContextProviderInfo> providers = properties->value(key)->info()->providers(); - if (providers.size() > 0) - out << "plugin: " << providers.at(0).plugin << endl; - else - out << "no plugin for key:" << key << endl; + properties->value(key)->prop->waitForSubscription(); + out << "wait finished for " << key << endl; } else qDebug() << "no such key:" << key; - } else if (QString("constructionstring").startsWith(commandName)) { - QString key = args[0]; - if (properties->contains(key)) { - QList<ContextProviderInfo> providers = properties->value(key)->info()->providers(); - if (providers.size() > 0) - out << "constructionstring: " << providers.at(0).constructionString << endl; - else - out << "no constructionString for key:" << key << endl; - } else + } else if (QString("unsubscribe").startsWith(commandName)) { + foreach (QString key, args) + if (properties->contains(key)) + properties->value(key)->prop->unsubscribe(); + else qDebug() << "no such key:" << key; - } else if (QString("providers").startsWith(commandName)) { - QString key = args[0]; - if (properties->contains(key)) { - out << "providers: "; - QList<ContextProviderInfo> providers = properties->value(key)->info()->providers(); + } else if (QString("value").startsWith(commandName)) { + QString key = args[0]; + QString defaultValue; + if (args.size() > 1) + defaultValue = args[1]; + if (properties->contains(key)) { + PropertyListener *pl = properties->value(key); + out << "value: " << pl->valueToString(defaultValue) << endl; + } else + qDebug() << "no such key:" << key; + } else if (QString("key").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) + out << "key: " << properties->value(key)->prop->key() << endl; + else + qDebug() << "no such key:" << key; + } else if (QString("ikey").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) + out << "ikey: " << properties->value(key)->prop->info()->key() << endl; + else + qDebug() << "no such key:" << key; + } else if (QString("man").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) + out << "man: " << properties->value(key)->prop->info()->doc() << endl; + else + qDebug() << "no such key:" << key; + } else if (QString("type").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) + out << "type: " << properties->value(key)->prop->info()->type() << endl; + else + qDebug() << "no such key:" << key; + } else if (QString("plugin").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) { + QList<ContextProviderInfo> providers = properties->value(key)->prop->info()->providers(); + if (providers.size() > 0) + out << "plugin: " << providers.at(0).plugin << endl; + else + out << "no plugin for key:" << key << endl; + } else + qDebug() << "no such key:" << key; + } else if (QString("constructionstring").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) { + QList<ContextProviderInfo> providers = properties->value(key)->prop->info()->providers(); + if (providers.size() > 0) + out << "constructionstring: " << providers.at(0).constructionString << endl; + else + out << "no constructionString for key:" << key << endl; + } else + qDebug() << "no such key:" << key; + } else if (QString("providers").startsWith(commandName)) { + QString key = args[0]; + if (properties->contains(key)) { + out << "providers: "; + QList<ContextProviderInfo> providers = properties->value(key)->prop->info()->providers(); - foreach(ContextProviderInfo info, providers) - out << info.constructionString << "@" << info.plugin << " "; + foreach(ContextProviderInfo info, providers) + out << info.constructionString << "@" << info.plugin << " "; - out << endl; - } else - qDebug() << "no such key:" << key; - } else if (QString("flush").startsWith(commandName)) { - out << "FLUSHED" << endl; - out.flush(); - err << "FLUSHED" << endl; - err.flush(); + out << endl; } else - help(); - } + qDebug() << "no such key:" << key; + } else + help(); } diff --git a/libcontextsubscriber/cli/commandwatcher.h b/libcontextsubscriber/cli/commandwatcher.h index 6d283ea1..3eaa55b6 100644 --- a/libcontextsubscriber/cli/commandwatcher.h +++ b/libcontextsubscriber/cli/commandwatcher.h @@ -28,18 +28,19 @@ class QTextStream; class QSocketNotifier; class ContextProperty; class QString; +class PropertyListener; template <typename K, typename V> class QMap; class CommandWatcher : public QObject { Q_OBJECT public: - CommandWatcher(int commandfd, QMap<QString, ContextProperty*> *properties, QObject *parent = 0); + CommandWatcher(int commandfd, QMap<QString, PropertyListener*> *properties, QObject *parent = 0); private: int commandfd; QSocketNotifier *commandNotifier; void interpret(const QString& command) const; - QMap<QString, ContextProperty*> *properties; + QMap<QString, PropertyListener*> *properties; static void help(); private slots: diff --git a/libcontextsubscriber/cli/context-listen.cpp b/libcontextsubscriber/cli/context-listen.cpp index 978fe9ac..b84ee427 100644 --- a/libcontextsubscriber/cli/context-listen.cpp +++ b/libcontextsubscriber/cli/context-listen.cpp @@ -45,15 +45,12 @@ int main(int argc, char **argv) if (args.count() <= 1) qWarning() << "Started without properties, if you want properties at startup, pass them as arguments"; - QMap<QString, ContextProperty*> properties; + QMap<QString, PropertyListener*> properties; args.pop_front(); - foreach (QString key, args) { - if (properties[key] == 0) { - properties[key] = new ContextProperty(key, QCoreApplication::instance()); - new PropertyListener(properties[key]); - } - } + foreach (QString key, args) + if (!properties.contains(key)) + properties.insert(key, new PropertyListener(key)); new CommandWatcher(STDIN_FILENO, &properties, QCoreApplication::instance()); diff --git a/libcontextsubscriber/cli/propertylistener.cpp b/libcontextsubscriber/cli/propertylistener.cpp index 3d6a1eb5..740919a6 100644 --- a/libcontextsubscriber/cli/propertylistener.cpp +++ b/libcontextsubscriber/cli/propertylistener.cpp @@ -24,22 +24,41 @@ #include "sconnect.h" #include <QDebug> #include <QVariant> +#include <QCoreApplication> +#include <QDBusArgument> +#include <qjson/serializer.h> +#include <qjson/parser.h> -PropertyListener::PropertyListener(ContextProperty *prop) : - QObject(prop), prop(prop) +PropertyListener::PropertyListener(const QString &key): + QObject(QCoreApplication::instance()), prop(new ContextProperty(key, this)) { sconnect(prop, SIGNAL(valueChanged()), this, SLOT(onValueChanged())); qDebug() << prop->key() << " subscribtion started"; } -void PropertyListener::onValueChanged() +QString PropertyListener::valueToString(QString defaultValue) const { - QTextStream out(stdout); - out << prop->key(); - if (prop->value().isNull()) { - out << " is Unknown"; + QVariant value; + if (!defaultValue.isEmpty()) { + bool isOk; + QVariant def = QJson::Parser().parse(defaultValue.toUtf8(), &isOk); + if (!isOk) + qWarning() << "failed to parse default value as json:" << defaultValue; + value = prop->value(def); } else { - out << " = " << prop->value().typeName() << ":" << prop->value().toString(); + value = prop->value(); } - out << endl; + QString result; + if (value.isNull()) + return result += "Unknown"; + result += value.typeName(); + result += ':'; + result += QJson::Serializer().serialize(value); + return result; +} + +void PropertyListener::onValueChanged() +{ + QTextStream out(stdout); + out << prop->key() << " = " << valueToString() << endl; } diff --git a/libcontextsubscriber/cli/propertylistener.h b/libcontextsubscriber/cli/propertylistener.h index 8f2fd856..b15594b5 100644 --- a/libcontextsubscriber/cli/propertylistener.h +++ b/libcontextsubscriber/cli/propertylistener.h @@ -30,10 +30,11 @@ class PropertyListener : public QObject { Q_OBJECT public: - PropertyListener(ContextProperty *prop); + PropertyListener(const QString &key); + QString valueToString(QString defaultValue = QString()) const; private slots: void onValueChanged(); -private: +public: ContextProperty *prop; }; diff --git a/libcontextsubscriber/customer-tests/commander/commander_nonexistent.py b/libcontextsubscriber/customer-tests/commander/commander_nonexistent.py index b702cac7..b10d4a67 100755 --- a/libcontextsubscriber/customer-tests/commander/commander_nonexistent.py +++ b/libcontextsubscriber/customer-tests/commander/commander_nonexistent.py @@ -57,7 +57,7 @@ class CommanderNonExistent(unittest.TestCase): # check the non-existent property commander.send("add string test.string barfoo") commander.expect("Added key: test.string") - self.assert_(listen.expect(wanted("test.string", "QString", "barfoo")), + self.assert_(listen.expect(wanted("test.string", "QString", "\"barfoo\"")), "Non-existent property couldn't be commanded") # change the type of the non-existent property diff --git a/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py b/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py index f49b5406..a1ee1fbe 100755 --- a/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py +++ b/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py @@ -54,14 +54,14 @@ class Subscription(unittest.TestCase): #print "now reading" # Expect value coming from plugin libcontextsubscribertime1 - self.assert_(self.context_client.expect("Test.Time = QString:Time1:")) + self.assert_(self.context_client.expect("Test.Time = QString:\"Time1:")) # Modify the registry so that the key is now provided by libcontextsubscribertime2 os.system('cp time2.context.temp time.context.temp') os.system('mv time.context.temp time.context') # Expect value coming from plugin libcontextsubscribertime2 - self.assert_(self.context_client.expect("Test.Time = QString:Time2:")) + self.assert_(self.context_client.expect("Test.Time = QString:\"Time2:")) self.context_client.wait() if __name__ == "__main__": diff --git a/libcontextsubscriber/customer-tests/subscription/multiprovider2.py b/libcontextsubscriber/customer-tests/subscription/multiprovider2.py index 402765f8..34a3c3ae 100755 --- a/libcontextsubscriber/customer-tests/subscription/multiprovider2.py +++ b/libcontextsubscriber/customer-tests/subscription/multiprovider2.py @@ -70,7 +70,7 @@ class MultiProvider(unittest.TestCase): time.sleep(4) client.send("value test.prop") - self.assert_(client.expect("\nvalue: int:22\n")) + self.assert_(client.expect("^value: int:22$")) client.wait() provider_y.wait() provider_y.wait() diff --git a/libcontextsubscriber/customer-tests/subscription/subscription.py b/libcontextsubscriber/customer-tests/subscription/subscription.py index 4bd95ef5..3e941de7 100755 --- a/libcontextsubscriber/customer-tests/subscription/subscription.py +++ b/libcontextsubscriber/customer-tests/subscription/subscription.py @@ -69,7 +69,7 @@ class Subscription(unittest.TestCase): self.assert_( listen.expect(["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"]), "Actual key values pairs do not match expected") @@ -80,7 +80,7 @@ class Subscription(unittest.TestCase): listen.expect("^value: int:100$"), "Value command returned wrong value") - listen.send("value test.int defaultValue") + listen.send("value test.int \"defaultValue\"") self.assert_( listen.expect("^value: int:100$"), "Value command returned wrong value") @@ -89,12 +89,12 @@ class Subscription(unittest.TestCase): listen.expect("Unknown") # wait for it listen.send("value test.int") self.assert_( - listen.expect("^value is Unknown$"), + listen.expect("^value: Unknown$"), "Value command returned wrong value") - listen.send("value test.int defaultValue") + listen.send("value test.int \"defaultValue\"") self.assert_( - listen.expect("^value: QString:defaultValue$"), + listen.expect("^value: QString:\"defaultValue\"$"), "Value command returned wrong value") listen.send("key test.int") @@ -139,7 +139,7 @@ class Subscription(unittest.TestCase): listen = CLTool("context-listen", "test.double", "test.string", "test.int", "test.truth") listen.expect(["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"]) # wait for it listen.send("ikey test.int") @@ -171,7 +171,7 @@ class Subscription(unittest.TestCase): listen = CLTool("context-listen", "test.double", "test.string", "test.int", "test.truth", "test.fake") listen.expect(["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"]) # wait for it # test querying the type of all properties @@ -210,7 +210,7 @@ class Subscription(unittest.TestCase): listen = CLTool("context-listen", "test.double", "test.string", "test.int", "test.truth", "test.fake") listen.expect(["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"]) # wait for it # test querying the provider(s) @@ -256,7 +256,7 @@ class Subscription(unittest.TestCase): self.assert_( listen.expect(["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"]), "Actual key values pairs do not match expected") listen.wait() @@ -295,7 +295,7 @@ class Subscription(unittest.TestCase): provider.send("unset test.truth") self.assert_( - listen.expect("^test.truth is Unknown$"), + listen.expect(wantedUnknown("test.truth")), "setting to unknown didn't work") provider.send("test.truth = True") @@ -332,17 +332,17 @@ class Subscription(unittest.TestCase): listen = CLTool("context-listen", "test.string") self.assert_( - listen.expect("^test.string = QString:something$"), + listen.expect("^test.string = QString:\"something\"$"), "setting to 'something' didn't work") provider.send('test.string = ""') self.assert_( - listen.expect("^test.string = QString:$"), + listen.expect("^test.string = QString:\"\"$"), "setting to empty string didn't work") provider.send('unset test.string') self.assert_( - listen.expect("^test.string is Unknown$"), + listen.expect(wantedUnknown("test.string")), "setting to null didn't work") listen.wait() @@ -393,16 +393,16 @@ class MultipleSubscribers(unittest.TestCase): client1_expected = ["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"] client2_expected = ["^test.double = double:2.5$", "^test.int = int:1$"] client3_expected = ["^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"] client4_expected = ["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$"] + "^test.string = QString:\"foobar\"$"] self.assert_(self.context_client1.expect(client1_expected), "Actual key values pairs do not match expected") self.assert_(self.context_client2.expect(client2_expected), "Actual key values pairs do not match expected") @@ -431,16 +431,16 @@ class MultipleSubscribers(unittest.TestCase): """ client1_expected = ["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"] client2_expected = ["^test.double = double:2.5$", "^test.int = int:1$"] client3_expected = ["^test.int = int:1$", - "^test.string = QString:foobar$", + "^test.string = QString:\"foobar\"$", "^test.truth = bool:true$"] client4_expected = ["^test.double = double:2.5$", "^test.int = int:1$", - "^test.string = QString:foobar$"] + "^test.string = QString:\"foobar\"$"] self.assert_(self.context_client1.expect(client1_expected), "Actual key values pairs do not match expected") self.assert_(self.context_client2.expect(client2_expected), "Actual key values pairs do not match expected") @@ -463,8 +463,8 @@ class MultipleSubscribers(unittest.TestCase): self.assert_(self.context_client3.expect(client3_expected), "Actual key values pairs do not match expected") self.flexiprovider.send("unset test.truth") - client1_expected = "^test.truth is Unknown$" - client3_expected = "^test.truth is Unknown$" + client1_expected = wantedUnknown("test.truth") + client3_expected = wantedUnknown("test.truth") self.assert_(self.context_client1.expect(client1_expected), "Actual key values pairs do not match expected") self.assert_(self.context_client3.expect(client3_expected), "Actual key values pairs do not match expected") diff --git a/libcontextsubscriber/src/contextkitplugin.cpp b/libcontextsubscriber/src/contextkitplugin.cpp index ec43638f..4a905177 100644 --- a/libcontextsubscriber/src/contextkitplugin.cpp +++ b/libcontextsubscriber/src/contextkitplugin.cpp @@ -263,12 +263,57 @@ void ContextKitPlugin::onDBusValuesChanged(QMap<QString, QVariant> values) emit valueChanged(key, values[key]); } +// QDBus doesn't unmarshall non-basic types inside QVariants (since it cannot +// know the intention), but leaves them as QDBusArguments. Here we walk the +// structure and unpack lists and maps. +static QVariant demarshallValue(const QVariant &v) +{ + if (v.userType() != qMetaTypeId<QDBusArgument>()) + return v; + const QDBusArgument &dba = v.value<QDBusArgument>(); + switch (dba.currentType()) { + case QDBusArgument::ArrayType: { + QVariantList vl; + dba.beginArray(); + while (!dba.atEnd()) { + QVariant v; + dba >> v; + vl << demarshallValue(v); + } + dba.endArray(); + return QVariant(vl); + break; + } + case QDBusArgument::MapType: { + dba.beginMap(); + QVariantMap vm; + while (!dba.atEnd()) { + QString k; + QVariant v; + dba.beginMapEntry(); + dba >> k >> v; + dba.endMapEntry(); + v = demarshallValue(v); + vm.insert(k, v); + } + return QVariant(vm); + break; + } + default: + // Shouldn't reach this. + contextWarning() << "got something unexpected: QDBusArgument of type" + << dba.currentType(); + return QVariant(); + break; + } +} + static TimedValue createTimedValue(const QList<QVariant> value, quint64 time) { if (value.size() == 0) return TimedValue(QVariant(), time); else - return TimedValue(value.at(0), time); + return TimedValue(demarshallValue(value.at(0)), time); } void ContextKitPlugin::onNewValueChanged(QList<QVariant> value, diff --git a/libcontextsubscriber/src/propertyhandle.cpp b/libcontextsubscriber/src/propertyhandle.cpp index 73a88877..fd93988c 100644 --- a/libcontextsubscriber/src/propertyhandle.cpp +++ b/libcontextsubscriber/src/propertyhandle.cpp @@ -255,7 +255,8 @@ void PropertyHandle::onValueChanged() } else if (myType == "DOUBLE") { checked = (QVariant::Double == newValue.type()); } else if (myType == "INT") { - checked = (QVariant::Int == newValue.type()); + checked = (QVariant::ULongLong == newValue.type() || + QVariant::Int == newValue.type()); } if (!checked) { diff --git a/python/ContextKit/cltool.py b/python/ContextKit/cltool.py index 5901ab25..8051aadc 100644 --- a/python/ContextKit/cltool.py +++ b/python/ContextKit/cltool.py @@ -208,6 +208,6 @@ def wanted(name, type, value): def wantedUnknown(name): """Construct an expect() regexp expecting an unset context property.""" - return "^%s is Unknown$" % (name) + return "^%s = Unknown$" % (name) __all__ = ['wanted', 'wantedUnknown', 'CLTool'] |