32 #include <kwindowsystem.h>
33 #include <knotification.h>
35 #include <kiconloader.h>
36 #include <ktoolinvocation.h>
38 #include <QtCore/QStringList>
39 #include <QtDBus/QDBusConnectionInterface>
40 #include <QtDBus/QDBusInterface>
41 #include <QtDBus/qdbusconnection.h>
42 #include <QtXml/QDomDocument>
43 #include <QScriptEngine>
47 DBusInterface::DBusInterface() {
62 QStringList DBusInterface::allRegisteredPrograms() {
63 QDBusConnectionInterface *dBusIface = QDBusConnection::sessionBus().interface();
64 return dBusIface->registeredServiceNames();
68 QStringList returnList;
70 QStringList allServices = allRegisteredPrograms();
73 for (
int i = 0; i < allServices.size(); ++i) {
74 QString tmp = allServices.at(i);
76 QRegExp r1( QLatin1String(
"[a-zA-Z]{1,3}\\.[a-zA-Z0-9-]+\\.[a-zA-Z0-9_-\\.]+" ));
77 if (!r1.exactMatch(tmp)) {
80 if (
nodes(tmp).isEmpty()) {
83 QRegExp r2( QLatin1String(
"[a-zA-Z0-9_\\.-]+-[0-9]+" ));
84 if (r2.exactMatch(tmp)) {
85 tmp.truncate(tmp.lastIndexOf( QLatin1Char(
'-' )));
87 if (!returnList.contains(tmp)) {
97 return getNodes(program, QLatin1String(
"/"));
98 kDebug() <<
"getting Nodes of" << program;
99 QDBusInterface dBusIface(program, QLatin1String(
"/" ), QLatin1String(
"org.freedesktop.DBus.Introspectable" ));
100 QDBusMessage msg = QDBusMessage::createMethodCall(program, QLatin1String(
"/" ), QLatin1String(
"org.freedesktop.DBus.Introspectable" ), QLatin1String(
"Introspect" ));
101 QDBusReply<QString> response = dBusIface.connection().call(msg, QDBus::Block, 1);
104 domDoc.setContent(response);
105 if (domDoc.toString().isEmpty()) {
106 kDebug() <<
"no reply from" << program;
107 QStringList instances = allRegisteredPrograms().filter(program);
108 if (!instances.isEmpty()) {
109 QDBusInterface iFace(instances.first(), QLatin1String(
"/" ), QLatin1String(
"org.freedesktop.DBus.Introspectable" ));
110 QDBusMessage msg = QDBusMessage::createMethodCall(instances.first(), QLatin1String(
"/" ), QLatin1String(
"org.freedesktop.DBus.Introspectable" ), QLatin1String(
"Introspect" ));
111 QDBusReply<QString> response = iFace.connection().call(msg, QDBus::Block, 1);
113 domDoc.setContent(response);
116 kDebug() <<
"got Nodes of" << program;
118 QDomElement node = domDoc.documentElement();
120 QDomElement child = node.firstChildElement();
121 QStringList returnList;
122 while (!child.isNull()) {
123 if (child.tagName() == QLatin1String(
"node")) {
124 QString name = child.attribute(QLatin1String(
"name"));
125 if (name != QLatin1String(
"org" ) && name != QLatin1String(
"modules" ) && !
functions(program, name).isEmpty()) {
129 child = child.nextSiblingElement();
134 QStringList DBusInterface::getNodes(
const QString& service,
const QString& node)
137 QDBusMessage msg = QDBusMessage::createMethodCall(service, node, QLatin1String(
"org.freedesktop.DBus.Introspectable" ), QLatin1String(
"Introspect" ));
138 QDBusReply<QString> response = QDBusConnection::sessionBus().call(msg, QDBus::Block, 1);
141 domDoc.setContent(response);
142 if (domDoc.toString().isEmpty()) {
143 kDebug() <<
"no reply from" << service;
144 QStringList instances = allRegisteredPrograms().filter(service);
145 if (!instances.isEmpty()) {
146 QDBusMessage msg = QDBusMessage::createMethodCall(instances.first(), node, QLatin1String(
"org.freedesktop.DBus.Introspectable" ), QLatin1String(
"Introspect" ));
147 QDBusReply<QString> response = QDBusConnection::sessionBus().call(msg, QDBus::Block, 1);
149 domDoc.setContent(response);
153 QDomElement child = domDoc.documentElement().firstChildElement();
154 while (!child.isNull()) {
155 if (child.tagName() == QLatin1String(
"node")) {
156 QString name = child.attribute(QLatin1String(
"name"));
157 kDebug() <<
"got node:" << service << node + name;
158 if (node.endsWith(
"/")) {
161 name = node + QLatin1String(
"/") + name;
164 nodes << getNodes(service, name);
166 child = child.nextSiblingElement();
174 QDBusInterface dBusIface(program,
object, QLatin1String(
"org.freedesktop.DBus.Introspectable" ));
175 QDBusReply<QString> response = dBusIface.call(QLatin1String(
"Introspect" ));
178 domDoc.setContent(response);
180 if (domDoc.toString().isEmpty()) {
181 QStringList instances = allRegisteredPrograms().filter(program);
182 if (!instances.isEmpty()) {
183 QDBusInterface iFace(instances.first(), QLatin1Char(
'/' ) + object, QLatin1String(
"org.freedesktop.DBus.Introspectable" ));
184 response = iFace.call(QLatin1String(
"Introspect" ));
185 domDoc.setContent(response);
189 QDomElement node = domDoc.documentElement();
190 QDomElement child = node.firstChildElement();
192 QMultiMap<QString, Prototype> funcList;
194 while (!child.isNull()) {
195 if (child.tagName() == QLatin1String(
"interface")) {
196 if (child.attribute(QLatin1String(
"name" )) == QLatin1String(
"org.freedesktop.DBus.Properties" ) ||
197 child.attribute(QLatin1String(
"name" )) == QLatin1String(
"org.freedesktop.DBus.Introspectable" )) {
198 child = child.nextSiblingElement();
201 QString
interface = child.attribute(QLatin1String("name"));
202 QDomElement subChild = child.firstChildElement();
203 while (!subChild.isNull()) {
204 if (subChild.tagName() == QLatin1String(
"method")) {
205 QString functionName = subChild.attribute(QLatin1String(
"name"));
206 QDomElement argDom = subChild.firstChildElement();
207 QList<Argument> argList;
208 while (!argDom.isNull()) {
210 if (argDom.tagName() == QLatin1String(
"arg")) {
211 QString tmpArg = argDom.attribute(QLatin1String(
"type"));
212 if (tmpArg == QLatin1String(
"i" )) {
214 }
else if (tmpArg == QLatin1String(
"u" )) {
216 }
else if (tmpArg == QLatin1String(
"x" )) {
217 argument.
setValue(QVariant::LongLong);
218 }
else if (tmpArg == QLatin1String(
"s" )) {
219 argument.
setValue(QVariant::String);
220 }
else if (tmpArg == QLatin1String(
"b" )) {
222 }
else if (tmpArg == QLatin1String(
"d" )) {
223 argument.
setValue(QVariant::Double);
224 }
else if (tmpArg == QLatin1String(
"as" )) {
225 argument.
setValue(QVariant::StringList);
226 }
else if (tmpArg == QLatin1String(
"ay" )) {
227 argument.
setValue(QVariant::ByteArray);
229 argDom = argDom.nextSiblingElement();
233 if (argDom.attribute(QLatin1String(
"direction")) == QLatin1String(
"in" )) {
234 if (!argDom.attribute(QLatin1String(
"name")).isEmpty()) {
237 argument.
setDescription(i18nc(
"The name of a parameter",
"unknown"));
239 argList.append(argument);
242 argDom = argDom.nextSiblingElement();
244 Prototype function(functionName, argList);
245 if(!funcList.contains(interface,
function)){
246 funcList.insertMulti(interface,
function);
249 subChild = subChild.nextSiblingElement();
252 child = child.nextSiblingElement();
259 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
260 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"configuredRemotes" ));
261 QDBusMessage response = QDBusConnection::sessionBus().call(m);
262 if (response.type() == QDBusMessage::ErrorMessage) {
263 kDebug() << response.errorMessage();
265 remotes = response.arguments().at(0).toStringList();
271 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
272 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"considerButtonEvents" ));
274 QDBusMessage response = QDBusConnection::sessionBus().call(m);
275 if (response.type() == QDBusMessage::ErrorMessage) {
276 kDebug() << response.errorMessage();
281 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
282 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"ignoreButtonEvents" ));
284 QDBusMessage response = QDBusConnection::sessionBus().call(m);
285 if (response.type() == QDBusMessage::ErrorMessage) {
286 kDebug() << response.errorMessage();
291 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
292 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"reloadConfiguration" ));
293 QDBusMessage response = QDBusConnection::sessionBus().call(m);
294 if (response.type() == QDBusMessage::ErrorMessage) {
295 kDebug() << response.errorMessage();
301 QDBusConnectionInterface *dBusIface = QDBusConnection::sessionBus().interface();
302 if (dBusIface->isServiceRegistered(program)) {
309 QStringList instances = allRegisteredPrograms().filter(program);
310 kDebug() <<
"instances of " << program << instances;
314 if(instances.count() != 1){
320 QRegExp r2( QLatin1String(
"[a-zA-Z0-9_\\.-]+-[0-9]+" ));
321 if(r2.exactMatch(instances.first())){
328 bool DBusInterface::searchForProgram(
const DBusAction *action, QStringList &programs) {
329 QDBusConnectionInterface *dBusIface = QDBusConnection::sessionBus().interface();
335 kDebug() <<
"searching for prog:" << service;
336 if (dBusIface->isServiceRegistered(service)) {
337 kDebug() <<
"adding Program: " << service;
340 kDebug() <<
"nope... " << service <<
" not here.";
345 const QStringList buf = dBusIface->registeredServiceNames();
347 for (QStringList::const_iterator i = buf.constBegin(); i != buf.constEnd(); ++i) {
348 QString program = *i;
353 if (programs.size() == 1) {
354 kDebug() <<
"Yeah! found it!";
355 }
else if (programs.size() == 0) {
356 kDebug() <<
"Nope... not here...";
358 kDebug() <<
"found multiple instances...";
362 kDebug() <<
"Multiple instances of" << action->
application() <<
"found but destination is set to None";
365 QList<WId> s = KWindowSystem::stackingOrder();
367 for (
int i = 0; i < s.size(); i++) {
368 int p = KWindowSystem::windowInfo(s.at(i), NET::WMPid).win();
369 QString
id = action->
application() + QLatin1Char(
'-' ) + QString().setNum(p);
370 if (programs.contains(
id)) {
376 while (programs.size() > 1) programs.removeLast();
378 QList<WId> s = KWindowSystem::stackingOrder();
380 for (
int i = 0; i < s.size(); ++i) {
381 int p = KWindowSystem::windowInfo(s.at(i), NET::WMPid).win();
382 QString
id = action->
application() + QLatin1Char(
'-' ) + QString().setNum(p);
383 if (programs.contains(
id)) {
389 while (programs.size() > 1) programs.removeFirst();
392 kDebug() <<
"returning true";
397 kDebug() <<
"executeAction called";
398 QDBusConnectionInterface *dBusIface = QDBusConnection::sessionBus().interface();
400 QStringList programs;
402 if (!searchForProgram(action, programs)) {
407 kDebug() <<
"Autostart: " << action->
autostart();
408 kDebug() <<
"programs.size: " << programs.size();
409 if (action->
autostart() && !programs.size()) {
410 kDebug() <<
"Should start " << action->
application();
412 runCommand.remove(QRegExp( QLatin1String(
"org.[a-zA-Z0-9]*." )));
413 kDebug() <<
"runCommand" << runCommand;
414 KToolInvocation::startServiceByDesktopName(runCommand);
419 if (!searchForProgram(action, programs)) {
420 kDebug() <<
"Failed to start the application" << action->
application();
424 for (QStringList::iterator i = programs.begin(); i != programs.end(); ++i) {
425 const QString &program = *i;
426 kDebug() <<
"Searching DBus for program:" << program;
427 if (dBusIface->isServiceRegistered(program)) {
428 kDebug() <<
"Sending data (" << program <<
", " << action->
node() <<
", " << action->
interface() <<
". " << action->
function().
name();
431 QString scriptText = action->
function().
name().remove(0, 7);
433 QScriptEngine scriptEngine;
435 QScriptValue objectValue = scriptEngine.newQObject(appIface);
436 scriptEngine.globalObject().setProperty(
"dbus", objectValue);
439 QScriptValue argValue;
440 switch(arg.
value().type()) {
442 case QVariant::LongLong:
443 argValue = QScriptValue(arg.
value().toInt());
446 argValue = QScriptValue(arg.
value().toUInt());
448 case QVariant::Double:
449 argValue = QScriptValue(arg.
value().toDouble());
452 argValue = QScriptValue(arg.
value().toBool());
454 case QVariant::StringList:
455 argValue = QScriptValue(arg.
value().toStringList().join(
","));
457 case QVariant::ByteArray:
458 case QVariant::String:
459 argValue = QScriptValue(arg.
value().toString());
461 argValue = QScriptValue(arg.
value().toInt());
464 scriptEngine.globalObject().setProperty(
"arg" + QString::number(argCount++), argValue);
466 qDebug() <<
"its a script:" << scriptText;
467 scriptEngine.evaluate(scriptText);
470 QDBusMessage m = QDBusMessage::createMethodCall(program, action->
node(), action->
interface(), action->
function().
name());
473 kDebug() <<
"Got argument:" << arg.
value().type() <<
"value" << arg.
value();
476 QDBusMessage response = QDBusConnection::sessionBus().call(m);
477 if (response.type() == QDBusMessage::ErrorMessage) {
478 kDebug() << response.errorMessage();
486 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
487 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"changeMode" ));
490 QDBusReply<bool> reply = QDBusConnection::sessionBus().call(m);
491 if(!reply.isValid()){
492 kDebug() <<
"Couldn't change to mode " << modeName <<
" on remote " << remoteName;
497 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
498 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"currentMode" ));
500 QDBusReply<QString> reply = QDBusConnection::sessionBus().call(m);
501 if (reply.isValid()) {
504 kDebug() << reply.error().message();
510 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
511 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"modesForRemote" ));
513 QDBusReply<QStringList> reply = QDBusConnection::sessionBus().call(m);
514 if (reply.isValid()) {
517 kDebug() << reply.error().message();
518 return QStringList();
523 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
524 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"modeIcon" ));
527 QDBusReply<QString> reply = QDBusConnection::sessionBus().call(m);
528 if (reply.isValid()) {
531 kDebug() << reply.error().message();
532 return QLatin1String(
"" );
538 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/modules/kremotecontroldaemon" ),
539 QLatin1String(
"org.kde.krcd" ), QLatin1String(
"eventsIgnored" ));
541 QDBusReply<bool> reply = QDBusConnection::sessionBus().call(m);
542 if (reply.isValid()) {
545 kDebug() << reply.error().message();
551 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/kded" ), QLatin1String(
"org.kde.kded" ), QLatin1String(
"loadedModules" ));
552 QDBusReply<QStringList> reply = QDBusConnection::sessionBus().call(m);
554 return reply.value().contains(QLatin1String(
"kremotecontroldaemon" ));
556 kDebug() << reply.error().message();
561 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/kded" ), QLatin1String(
"org.kde.kded" ), QLatin1String(
"loadModule" ));
562 m << QLatin1String(
"kremotecontroldaemon" );
563 QDBusReply<bool> reply = QDBusConnection::sessionBus().call(m);
564 if(!reply.isValid() || !reply.value()){
568 m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/kded" ), QLatin1String(
"org.kde.kded" ), QLatin1String(
"setModuleAutoloading" ));
569 m << QLatin1String(
"kremotecontroldaemon" ) <<
true;
570 QDBusConnection::sessionBus().call(m);
575 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/kded" ), QLatin1String(
"org.kde.kded" ), QLatin1String(
"unloadModule" ));
576 m << QLatin1String(
"kremotecontroldaemon" );
577 QDBusReply<bool> reply = QDBusConnection::sessionBus().call(m);
578 if(!reply.isValid() || !reply.value()){
582 m = QDBusMessage::createMethodCall(QLatin1String(
"org.kde.kded" ), QLatin1String(
"/kded" ), QLatin1String(
"org.kde.kded" ), QLatin1String(
"setModuleAutoloading" ));
583 m << QLatin1String(
"kremotecontroldaemon" ) <<
false;
584 QDBusConnection::sessionBus().call(m);
597 QDBusInterface iface(m_program, m_path);
598 qDebug() <<
"calling" << method;
599 QDBusReply<int> ret = iface.call(method);
600 qDebug() <<
"return value is" << ret.value();
606 QDBusInterface iface(m_program, m_path);
607 qDebug() <<
"calling" << method <<
"with arg" << value;
608 QDBusReply<int> ret = iface.call(method, value);
609 qDebug() <<
"return value is" << ret.value();
615 QDBusInterface iface(m_program, m_path);
616 qDebug() <<
"calling" << method <<
"with arg" << value;
617 QDBusReply<int> ret = iface.call(method, value);
618 qDebug() <<
"return value is" << ret.value();
int call(const QString &method)
ActionDestination destination() const
Prototype function() const
void setValue(const QVariant &value)
void considerButtonEvents(const QString &remoteName)
static DBusInterface * getInstance()
bool loadKdedModule()
Loads the kremotecontrol kded module and sets autoLoading to true.
void setDescription(const QString &description)
QDBusIfaceWrapper(const QString &program, const QString &path)
void reloadRemoteControlDaemon()
QStringList modesForRemote(const QString &remoteName)
QString modeIcon(const QString &remoteName, const QString &modeName)
QMultiMap< QString, Prototype > functions(const QString &program, const QString &object)
bool isKdedModuleRunning()
void changeMode(const QString &remoteName, const QString &modeName)
QStringList nodes(const QString &program)
bool isUnique(const QString &program)
QStringList registeredPrograms()
QString interface() const
QString currentMode(const QString &remoteName)
QList< Argument > args() const
bool eventsIgnored(const QString &remoteName)
bool isProgramRunning(const QString &program)
bool unloadKdedModule()
Unloads the kremotecontrol kded module and sets autoLoading to false.
QString application() const
QStringList configuredRemotes()
void ignoreButtonEvents(const QString &remoteName)
static DBusInterface * theInstance
void executeAction(const DBusAction *action)