QDBusViewer Class Reference

#include <qdbusviewer.h>

Inheritance diagram for QDBusViewer:

Inheritance graph
[legend]
Collaboration diagram for QDBusViewer:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 39 of file qdbusviewer.h.

Public Slots

void refresh ()

Public Member Functions

 QDBusViewer (const QDBusConnection &connection, QWidget *parent=0)

Private Slots

void serviceChanged (QTreeWidgetItem *item)
void showContextMenu (const QPoint &)
void connectionRequested (const BusSignature &sig)
void callMethod (const BusSignature &sig)
void dumpMessage (const QDBusMessage &msg)
void refreshChildren ()
void serviceRegistered (const QString &service)
void serviceUnregistered (const QString &service)
void serviceOwnerChanged (const QString &name, const QString &oldOwner, const QString &newOwner)
void activate (const QModelIndex &item)
void logError (const QString &msg)

Private Member Functions

void logMessage (const QString &msg)

Private Attributes

QDBusConnection c
QString currentService
QTreeViewtree
QActionrefreshAction
QTreeWidgetservices
QTextEditlog


Constructor & Destructor Documentation

QDBusViewer::QDBusViewer ( const QDBusConnection connection,
QWidget parent = 0 
)

Definition at line 47 of file qdbusviewer.cpp.

References activate(), QBoxLayout::addLayout(), QLayout::addWidget(), QBoxLayout::addWidget(), c, QObject::connect(), Qt::CustomContextMenu, QWidget::customContextMenuRequested(), QDBusConnection::interface(), QMetaObject::invokeMethod(), QDBusConnection::isConnected(), QDBusConnection::lastError(), QWidget::layout(), log, logError(), logMessage(), QDBusError::message(), Qt::QueuedConnection, QKeySequence::Refresh, refreshAction, refreshChildren(), serviceChanged(), serviceOwnerChanged(), serviceRegistered(), services, serviceUnregistered(), QWidget::setContextMenuPolicy(), QAction::setData(), QTreeWidget::setHeaderLabels(), QTextEdit::setReadOnly(), QTreeView::setRootIsDecorated(), QAction::setShortcut(), showContextMenu(), SIGNAL, SLOT, and tree.

00048     : QWidget(parent), c(connection)
00049 {
00050     services = new QTreeWidget;
00051     services->setRootIsDecorated(false);
00052     services->setHeaderLabels(QStringList("Services"));
00053 
00054     tree = new QTreeView;
00055     tree->setContextMenuPolicy(Qt::CustomContextMenu);
00056 
00057     connect(tree, SIGNAL(activated(const QModelIndex&)), this, SLOT(activate(const QModelIndex&)));
00058 
00059     refreshAction = new QAction(tr("&Refresh"), tree);
00060     refreshAction->setData(42); // increase the amount of 42 used as magic number by one
00061     refreshAction->setShortcut(QKeySequence::Refresh);
00062     connect(refreshAction, SIGNAL(triggered()), this, SLOT(refreshChildren()));
00063 
00064     QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, tree);
00065     connect(refreshShortcut, SIGNAL(activated()), this, SLOT(refreshChildren()));
00066 
00067     QVBoxLayout *topLayout = new QVBoxLayout(this);
00068     log = new QTextEdit;
00069     log->setReadOnly(true);
00070 
00071     QHBoxLayout *layout = new QHBoxLayout;
00072     layout->addWidget(services, 1);
00073     layout->addWidget(tree, 2);
00074 
00075     topLayout->addLayout(layout);
00076     topLayout->addWidget(log);
00077 
00078     connect(services, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
00079             this, SLOT(serviceChanged(QTreeWidgetItem*)));
00080     connect(tree, SIGNAL(customContextMenuRequested(QPoint)),
00081             this, SLOT(showContextMenu(QPoint)));
00082 
00083     QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
00084 
00085     if (c.isConnected()) {
00086         logMessage("Connected to D-Bus.");
00087         QDBusConnectionInterface *iface = c.interface();
00088         connect(iface, SIGNAL(serviceRegistered(QString)),
00089                 this, SLOT(serviceRegistered(QString)));
00090         connect(iface, SIGNAL(serviceUnregistered(QString)),
00091                 this, SLOT(serviceUnregistered(QString)));
00092         connect(iface, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00093                 this, SLOT(serviceOwnerChanged(QString,QString,QString)));
00094     } else {
00095         logError("Cannot connect to D-Bus: " + c.lastError().message());
00096     }
00097 }

Here is the call graph for this function:


Member Function Documentation

void QDBusViewer::refresh (  )  [slot]

Definition at line 109 of file qdbusviewer.cpp.

References c, QTreeWidget::clear(), QDBusConnection::interface(), QDBusConnectionInterface::registeredServiceNames(), and services.

00110 {
00111     services->clear();
00112 
00113     const QStringList serviceNames = c.interface()->registeredServiceNames();
00114     foreach (QString service, serviceNames)
00115         new QTreeWidgetItem(services, QStringList(service));
00116 }

void QDBusViewer::serviceChanged ( QTreeWidgetItem item  )  [private, slot]

Definition at line 345 of file qdbusviewer.cpp.

References c, QString::clear(), QObject::connect(), currentService, logError(), QAbstractItemView::model(), QTreeView::setModel(), SIGNAL, SLOT, QTreeWidgetItem::text(), and tree.

Referenced by QDBusViewer().

00346 {
00347     delete tree->model();
00348 
00349     currentService.clear();
00350     if (!item)
00351         return;
00352     currentService = item->text(0);
00353 
00354     tree->setModel(new QDBusViewModel(currentService, c));
00355     connect(tree->model(), SIGNAL(busError(QString)), this, SLOT(logError(QString)));
00356 }

void QDBusViewer::showContextMenu ( const QPoint  )  [private, slot]

Definition at line 218 of file qdbusviewer.cpp.

References QMenu::addAction(), callMethod(), connectionRequested(), currentService, QAction::data(), QDBusModel::dBusInterface(), QDBusModel::dBusMethodName(), QDBusModel::dBusPath(), QMenu::exec(), QTreeView::indexAt(), QModelIndex::isValid(), QDBusModel::itemType(), QWidget::mapToGlobal(), QDBusModel::MethodItem, QModelIndex::model(), refreshAction, QAction::setData(), QDBusModel::SignalItem, QVariant::toInt(), tree, and QAbstractScrollArea::viewport().

Referenced by QDBusViewer().

00219 {
00220     QModelIndex item = tree->indexAt(point);
00221     if (!item.isValid())
00222         return;
00223 
00224     const QDBusModel *model = static_cast<const QDBusModel *>(item.model());
00225 
00226     BusSignature sig;
00227     sig.mService = currentService;
00228     sig.mPath = model->dBusPath(item);
00229     sig.mInterface = model->dBusInterface(item);
00230     sig.mName = model->dBusMethodName(item);
00231 
00232     QMenu menu;
00233     menu.addAction(refreshAction);
00234 
00235     switch (model->itemType(item)) {
00236     case QDBusModel::SignalItem: {
00237         QAction *action = new QAction("&Connect", &menu);
00238         action->setData(1);
00239         menu.addAction(action);
00240         break; }
00241     case QDBusModel::MethodItem: {
00242         QAction *action = new QAction("&Call", &menu);
00243         action->setData(2);
00244         menu.addAction(action);
00245         break; }
00246 #if 0
00247     case PropertyItem: {
00248         QAction *actionSet = new QAction("&Set value", &menu);
00249         actionSet->setData(3);
00250         QAction *actionGet = new QAction("&Get value", &menu);
00251         actionGet->setData(4);
00252         menu.addAction(actionSet);
00253         menu.addAction(actionGet);
00254         break; }
00255 #endif
00256     default:
00257         break;
00258     }
00259 
00260     QAction *selectedAction = menu.exec(tree->viewport()->mapToGlobal(point));
00261     if (!selectedAction)
00262         return;
00263 
00264     switch (selectedAction->data().toInt()) {
00265     case 1:
00266         connectionRequested(sig);
00267         break;
00268     case 2:
00269         callMethod(sig);
00270         break;
00271     }
00272 }

void QDBusViewer::connectionRequested ( const BusSignature sig  )  [private, slot]

Definition at line 274 of file qdbusviewer.cpp.

References c, QDBusConnection::connect(), dumpMessage(), logError(), BusSignature::mInterface, BusSignature::mName, BusSignature::mPath, BusSignature::mService, and SLOT.

Referenced by activate(), and showContextMenu().

00275 {
00276     if (!c.connect(sig.mService, QString(), sig.mInterface, sig.mName, this,
00277               SLOT(dumpMessage(QDBusMessage)))) {
00278         logError(QString("Unable to connect to service %1, path %2, interface %3, signal %4").arg(
00279                     sig.mService).arg(sig.mPath).arg(sig.mInterface).arg(sig.mName));
00280     }
00281 }

void QDBusViewer::callMethod ( const BusSignature sig  )  [private, slot]

Definition at line 147 of file qdbusviewer.cpp.

References QList< T >::at(), c, QDBusConnection::callWithCallback(), QList< T >::clear(), QVariant::convert(), QList< T >::count(), QDBusMessage::createMethodCall(), dumpMessage(), QByteArray::endsWith(), Qt::escape(), QString::fromLatin1(), QString::fromUtf8(), QInputDialog::getText(), i, QList< T >::isEmpty(), QString::length(), message, QDBusInterface::metaObject(), QMetaObject::method(), method, QMetaObject::methodCount(), BusSignature::mInterface, BusSignature::mName, BusSignature::mPath, BusSignature::mService, QVariant::nameToType(), QLineEdit::Normal, QMetaMethod::signature(), SLOT, QString::split(), QVariant::String, and QMessageBox::warning().

Referenced by activate(), and showContextMenu().

00148 {
00149     QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface, c);
00150     const QMetaObject *mo = iface.metaObject();
00151 
00152     // find the method
00153     QMetaMethod method;
00154     for (int i = 0; i < mo->methodCount(); ++i) {
00155         const QString signature = QString::fromLatin1(mo->method(i).signature());
00156         if (signature.startsWith(sig.mName) && signature.at(sig.mName.length()) == '(')
00157             method = mo->method(i);
00158     }
00159     if (!method.signature()) {
00160         QMessageBox::warning(this, "Unable to find method",
00161                 QString("Unable to find method %1 on path %2 in interface %3").arg(
00162                     sig.mName).arg(sig.mPath).arg(sig.mInterface));
00163         return;
00164     }
00165 
00166     QList<QByteArray> paramTypes = method.parameterTypes();
00167     int paramTypeCount = 0;
00168     foreach (QByteArray paramType, paramTypes) {
00169         if (paramType.endsWith('&'))
00170             continue; // ignore OUT parameters
00171 
00172         if (!QVariant(QVariant::nameToType(paramType)).canConvert(QVariant::String)) {
00173             QMessageBox::warning(this, "Unable to call method",
00174                     QString("Cannot marshall parameter of type %1").arg(
00175                         QVariant::nameToType(paramType)));
00176             return;
00177         }
00178         ++paramTypeCount;
00179     }
00180 
00181     QList<QVariant> arguments;
00182     if (!paramTypes.isEmpty()) {
00183         QString input;
00184         bool ok = true;
00185         while (arguments.isEmpty()) {
00186             input = QInputDialog::getText(this, "Arguments",
00187                     "Please enter the arguments for the call, separated by comma."
00188                     "<br>Example: <i>hello,world,2.3,-34</i><br><br><b>Signature:</b> "
00189                     + Qt::escape(QString::fromUtf8(method.signature())),
00190                     QLineEdit::Normal, input, &ok);
00191             if (!ok)
00192                 return;
00193 
00194             QStringList argStrings = input.split(',');
00195             if (argStrings.count() != paramTypeCount)
00196                 continue;
00197 
00198             for (int i = 0; i < argStrings.count(); ++i) {
00199                 if (paramTypes.at(i).endsWith('&'))
00200                     continue; // ignore OUT paramters
00201 
00202                 QVariant v = argStrings.at(i);
00203                 if (!v.convert(QVariant::nameToType(paramTypes.at(i)))) {
00204                     arguments.clear();
00205                     break;
00206                 }
00207                 arguments += v;
00208             }
00209         }
00210     }
00211 
00212     QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, sig.mInterface,
00213             sig.mName);
00214     message.setArguments(arguments);
00215     c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
00216 }

void QDBusViewer::dumpMessage ( const QDBusMessage msg  )  [private, slot]

Definition at line 283 of file qdbusviewer.cpp.

References QTextEdit::append(), QString::arg(), QVariant::canConvert(), QString::chop(), QDBusMessage::ErrorMessage, Qt::escape(), QString::fromLatin1(), QList< T >::isEmpty(), log, message, QVariant::Rect, QDBusMessage::ReplyMessage, QDBusMessage::SignalMessage, QVariant::String, QVariant::StringList, QVariant::toRect(), and QVariant::toStringList().

Referenced by callMethod(), and connectionRequested().

00284 {
00285     QList<QVariant> args = message.arguments();
00286     QString out = "Received ";
00287 
00288     switch (message.type()) {
00289     case QDBusMessage::SignalMessage:
00290         out += "signal ";
00291         break;
00292     case QDBusMessage::ErrorMessage:
00293         out += "error message ";
00294         break;
00295     case QDBusMessage::ReplyMessage:
00296         out += "reply ";
00297         break;
00298     default:
00299         out += "message ";
00300         break;
00301     }
00302 
00303     out += "from ";
00304     out += message.service();
00305     if (!message.path().isEmpty())
00306         out += ", path " + message.path();
00307     if (!message.interface().isEmpty())
00308         out += ", interface <i>" + message.interface() + "</i>";
00309     if (!message.member().isEmpty())
00310         out += ", member " + message.member();
00311     out += "<br>";
00312     if (!args.isEmpty()) {
00313         out += "&nbsp;&nbsp;Parameters: ";
00314         foreach (QVariant arg, args) {
00315             if (arg.canConvert(QVariant::StringList)) {
00316                 out += "<b>{</b>";
00317                 QStringList list = arg.toStringList();
00318                 foreach (QString item, list)
00319                     out += "<b>\"</b>" + Qt::escape(item) + "<b>\"</b>, ";
00320                 if (!list.isEmpty())
00321                     out.chop(2);
00322                 out += "<b>}</b>";
00323             } else if (arg.canConvert(QVariant::Rect)) {
00324                 QRect r = arg.toRect();
00325                 out += QString::fromLatin1("QRect(%1, %2, %3, %4)").arg(r.left()).arg(r.top()).arg(
00326                         r.right()).arg(r.bottom());
00327             } else if (qVariantCanConvert<QDBusArgument>(arg)) {
00328                 out += "[QDBusArgument: " + qvariant_cast<QDBusArgument>(arg).currentSignature();
00329                 out += "]";
00330             } else if (arg.canConvert(QVariant::String)) {
00331                 out += "<b>\"</b>" + Qt::escape(arg.toString()) + "<b>\"</b>";
00332             } else {
00333                 out += "[";
00334                 out += arg.typeName();
00335                 out += "]";
00336             }
00337             out += ", ";
00338         }
00339         out.chop(2);
00340     }
00341 
00342     log->append(out);
00343 }

void QDBusViewer::refreshChildren (  )  [private, slot]

Definition at line 395 of file qdbusviewer.cpp.

References QAbstractItemView::currentIndex(), QAbstractItemView::model(), QDBusModel::refresh(), and tree.

Referenced by QDBusViewer().

00396 {
00397     QDBusModel *model = qobject_cast<QDBusModel *>(tree->model());
00398     if (!model)
00399         return;
00400     model->refresh(tree->currentIndex());
00401 }

void QDBusViewer::serviceRegistered ( const QString service  )  [private, slot]

Definition at line 358 of file qdbusviewer.cpp.

References QDBusConnection::baseService(), c, and services.

Referenced by QDBusViewer(), and serviceOwnerChanged().

00359 {
00360     if (service == c.baseService())
00361         return;
00362 
00363     new QTreeWidgetItem(services, QStringList(service));
00364 }

void QDBusViewer::serviceUnregistered ( const QString service  )  [private, slot]

Definition at line 375 of file qdbusviewer.cpp.

References findItem(), name, and services.

Referenced by QDBusViewer().

00376 {
00377     delete findItem(services, name);
00378 }

void QDBusViewer::serviceOwnerChanged ( const QString name,
const QString oldOwner,
const QString newOwner 
) [private, slot]

Definition at line 380 of file qdbusviewer.cpp.

References findItem(), QString::isEmpty(), name, serviceRegistered(), and services.

Referenced by QDBusViewer().

00382 {
00383     QTreeWidgetItem *item = findItem(services, name);
00384 
00385     if (!item && oldOwner.isEmpty() && !newOwner.isEmpty())
00386         serviceRegistered(name);
00387     else if (item && !oldOwner.isEmpty() && newOwner.isEmpty())
00388         delete item;
00389     else if (item && !oldOwner.isEmpty() && !newOwner.isEmpty()) {
00390         delete item;
00391         serviceRegistered(name);
00392     }
00393 }

void QDBusViewer::activate ( const QModelIndex item  )  [private, slot]

Definition at line 118 of file qdbusviewer.cpp.

References callMethod(), connectionRequested(), currentService, QDBusModel::dBusInterface(), QDBusModel::dBusMethodName(), QDBusModel::dBusPath(), QModelIndex::isValid(), QDBusModel::itemType(), QDBusModel::MethodItem, QModelIndex::model(), QDBusModel::PropertyItem, and QDBusModel::SignalItem.

Referenced by QDBusViewer().

00119 {
00120     if (!item.isValid())
00121         return;
00122 
00123     const QDBusModel *model = static_cast<const QDBusModel *>(item.model());
00124 
00125     BusSignature sig;
00126     sig.mService = currentService;
00127     sig.mPath = model->dBusPath(item);
00128     sig.mInterface = model->dBusInterface(item);
00129     sig.mName = model->dBusMethodName(item);
00130 
00131     switch (model->itemType(item)) {
00132     case QDBusModel::SignalItem:
00133         connectionRequested(sig);
00134         break;
00135     case QDBusModel::MethodItem:
00136         callMethod(sig);
00137         break;
00138 #if 0
00139     case QDBusModel::PropertyItem:
00140         break;
00141 #endif
00142     default:
00143         break;
00144     }
00145 }

void QDBusViewer::logError ( const QString msg  )  [private, slot]

Definition at line 104 of file qdbusviewer.cpp.

References QTextEdit::append(), Qt::escape(), and log.

Referenced by connectionRequested(), QDBusViewer(), and serviceChanged().

00105 {
00106     log->append("<font color=\"red\">Error: </font>" + Qt::escape(msg) + "<br>");
00107 }

void QDBusViewer::logMessage ( const QString msg  )  [private]

Definition at line 99 of file qdbusviewer.cpp.

References QTextEdit::append(), and log.

Referenced by QDBusViewer().

00100 {
00101     log->append(msg + "\n");
00102 }


Member Data Documentation

QDBusConnection QDBusViewer::c [private]

Definition at line 67 of file qdbusviewer.h.

Referenced by callMethod(), connectionRequested(), QDBusViewer(), refresh(), serviceChanged(), and serviceRegistered().

QString QDBusViewer::currentService [private]

Definition at line 68 of file qdbusviewer.h.

Referenced by activate(), serviceChanged(), and showContextMenu().

QTreeView* QDBusViewer::tree [private]

Definition at line 69 of file qdbusviewer.h.

Referenced by QDBusViewer(), refreshChildren(), serviceChanged(), and showContextMenu().

QAction* QDBusViewer::refreshAction [private]

Definition at line 70 of file qdbusviewer.h.

Referenced by QDBusViewer(), and showContextMenu().

QTreeWidget* QDBusViewer::services [private]

Definition at line 71 of file qdbusviewer.h.

Referenced by QDBusViewer(), refresh(), serviceOwnerChanged(), serviceRegistered(), and serviceUnregistered().

QTextEdit* QDBusViewer::log [private]

Definition at line 72 of file qdbusviewer.h.

Referenced by dumpMessage(), logError(), logMessage(), and QDBusViewer().


The documentation for this class was generated from the following files:
Generated on Thu Mar 15 17:14:21 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1