demos/dbus-viewer/qdbusmodel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the demonstration applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qdbusmodel.h"
00025 
00026 #include <QtCore/qvector.h>
00027 #include <QtXml/QtXml>
00028 
00029 struct QDBusItem
00030 {
00031     inline QDBusItem(QDBusModel::Type aType, const QString &aName, QDBusItem *aParent = 0)
00032         : type(aType), parent(aParent), isPrefetched(type != QDBusModel::PathItem), name(aName)
00033         {}
00034     inline ~QDBusItem()
00035     {
00036         qDeleteAll(children);
00037     }
00038 
00039     QString path() const
00040     {
00041         Q_ASSERT(type == QDBusModel::PathItem);
00042 
00043         QString s;
00044         const QDBusItem *item = this;
00045         while (item) {
00046             s.prepend(item->name);
00047             item = item->parent;
00048         }
00049         if (s.length() > 1)
00050             s.chop(1); // remove tailing slash
00051         return s;
00052     }
00053 
00054     QDBusModel::Type type;
00055     QDBusItem *parent;
00056     QVector<QDBusItem *> children;
00057     bool isPrefetched;
00058     QString name;
00059     QString caption;
00060 };
00061 
00062 QDomDocument QDBusModel::introspect(const QString &path)
00063 {
00064     QDomDocument doc;
00065 
00066     QDBusInterface iface(service, path, "org.freedesktop.DBus.Introspectable", c);
00067     if (!iface.isValid()) {
00068         QDBusError err(iface.lastError());
00069         emit busError(QString("Cannot introspect object %1 at %2:\n  %3 (%4)\n").arg(path).arg(
00070                       service).arg(err.name()).arg(err.message()));
00071         return doc;
00072     }
00073 
00074     QDBusReply<QString> xml = iface.call("Introspect");
00075 
00076     if (!xml.isValid()) {
00077         QDBusError err(xml.error());
00078         if (err.isValid()) {
00079             emit busError(QString("Call to object %1 at %2:\n  %3 (%4) failed\n").arg(
00080                         path).arg(service).arg(err.name()).arg(err.message()));
00081         } else {
00082             emit busError(QString("Invalid XML received from object %1 at %2\n").arg(
00083                     path).arg(service));
00084         }
00085         return doc;
00086     }
00087 
00088     doc.setContent(xml);
00089     return doc;
00090 }
00091 
00092 void QDBusModel::addMethods(QDBusItem *parent, const QDomElement &iface)
00093 {
00094     Q_ASSERT(parent);
00095 
00096     QDomElement child = iface.firstChildElement();
00097     while (!child.isNull()) {
00098         QDBusItem *item = 0;
00099         if (child.tagName() == QLatin1String("method")) {
00100             item = new QDBusItem(QDBusModel::MethodItem,
00101                     child.attribute("name"), parent);
00102             item->caption = "Method: " + item->name;
00103         } else if (child.tagName() == QLatin1String("signal")) {
00104             item = new QDBusItem(QDBusModel::SignalItem,
00105                     child.attribute("name"), parent);
00106             item->caption = "Signal: " + item->name;
00107         } else if (child.tagName() == QLatin1String("property")) {
00108             item = new QDBusItem(QDBusModel::PropertyItem,
00109                     child.attribute("name"), parent);
00110             item->caption = "Property: " + item->name;
00111         } else {
00112             qDebug() << "addMethods: unknown tag:" << child.tagName();
00113         }
00114         if (item)
00115             parent->children.append(item);
00116 
00117         child = child.nextSiblingElement();
00118     }
00119 }
00120 
00121 void QDBusModel::addPath(QDBusItem *parent)
00122 {
00123     Q_ASSERT(parent);
00124 
00125     QString path = parent->path();
00126 
00127     QDomDocument doc = introspect(path);
00128     QDomElement node = doc.documentElement();
00129     QDomElement child = node.firstChildElement();
00130     while (!child.isNull()) {
00131         if (child.tagName() == QLatin1String("node")) {
00132             QDBusItem *item = new QDBusItem(QDBusModel::PathItem,
00133                         child.attribute("name") + QLatin1Char('/'), parent);
00134             parent->children.append(item);
00135 
00136             addMethods(item, child);
00137         } else if (child.tagName() == QLatin1String("interface")) {
00138             QDBusItem *item = new QDBusItem(QDBusModel::InterfaceItem,
00139                         child.attribute("name"), parent);
00140             parent->children.append(item);
00141 
00142             addMethods(item, child);
00143         } else {
00144             qDebug() << "addPath: Unknown tag name:" << child.tagName();
00145         }
00146         child = child.nextSiblingElement();
00147     }
00148 
00149     parent->isPrefetched = true;
00150 }
00151 
00152 QDBusModel::QDBusModel(const QString &aService, const QDBusConnection &connection)
00153     : service(aService), c(connection), root(0)
00154 {
00155     root = new QDBusItem(QDBusModel::PathItem, QLatin1String("/"));
00156 }
00157 
00158 QDBusModel::~QDBusModel()
00159 {
00160     delete root;
00161 }
00162 
00163 QModelIndex QDBusModel::index(int row, int column, const QModelIndex &parent) const
00164 {
00165     const QDBusItem *item = static_cast<QDBusItem *>(parent.internalPointer());
00166     if (!item)
00167         item = root;
00168 
00169     if (column != 0 || row < 0 || row >= item->children.count())
00170         return QModelIndex();
00171 
00172     return createIndex(row, 0, item->children.at(row));
00173 }
00174 
00175 QModelIndex QDBusModel::parent(const QModelIndex &child) const
00176 {
00177     QDBusItem *item = static_cast<QDBusItem *>(child.internalPointer());
00178     if (!item || !item->parent || !item->parent->parent)
00179         return QModelIndex();
00180 
00181     return createIndex(item->parent->parent->children.indexOf(item->parent), 0, item->parent);
00182 }
00183 
00184 int QDBusModel::rowCount(const QModelIndex &parent) const
00185 {
00186     QDBusItem *item = static_cast<QDBusItem *>(parent.internalPointer());
00187     if (!item)
00188         item = root;
00189     if (!item->isPrefetched)
00190         const_cast<QDBusModel *>(this)->addPath(item);
00191 
00192     return item->children.count();
00193 }
00194 
00195 int QDBusModel::columnCount(const QModelIndex &) const
00196 {
00197     return 1;
00198 }
00199 
00200 QVariant QDBusModel::data(const QModelIndex &index, int role) const
00201 {
00202     const QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00203     if (!item)
00204         return QVariant();
00205 
00206     if (role != Qt::DisplayRole)
00207         return QVariant();
00208 
00209     return item->caption.isEmpty() ? item->name : item->caption;
00210 }
00211 
00212 QVariant QDBusModel::headerData(int section, Qt::Orientation orientation, int role) const
00213 {
00214     if (role != Qt::DisplayRole || orientation == Qt::Vertical || section != 0)
00215         return QVariant();
00216 
00217     return QLatin1String("Methods");
00218 }
00219 
00220 QDBusModel::Type QDBusModel::itemType(const QModelIndex &index) const
00221 {
00222     const QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00223     return item ? item->type : PathItem;
00224 }
00225 
00226 void QDBusModel::refresh(const QModelIndex &aIndex)
00227 {
00228     QModelIndex index = aIndex;
00229     while (index.isValid() && static_cast<QDBusItem *>(index.internalPointer())->type != PathItem) {
00230         index = index.parent();
00231     }
00232 
00233     QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00234     if (!item)
00235         item = root;
00236 
00237     if (!item->children.isEmpty()) {
00238         beginRemoveRows(index, 0, item->children.count() - 1);
00239         qDeleteAll(item->children);
00240         item->children.clear();
00241         endRemoveRows();
00242     }
00243 
00244     addPath(item);
00245     if (!item->children.isEmpty()) {
00246         beginInsertRows(index, 0, item->children.count() - 1);
00247         endInsertRows();
00248     }
00249 }
00250 
00251 QString QDBusModel::dBusPath(const QModelIndex &aIndex) const
00252 {
00253     QModelIndex index = aIndex;
00254     while (index.isValid() && static_cast<QDBusItem *>(index.internalPointer())->type != PathItem) {
00255         index = index.parent();
00256     }
00257 
00258     QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00259     if (!item)
00260         item = root;
00261 
00262     return item->path();
00263 }
00264 
00265 QString QDBusModel::dBusInterface(const QModelIndex &index) const
00266 {
00267     QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00268     if (!item)
00269         return QString();
00270     if (item->type == InterfaceItem)
00271         return item->name;
00272     if (item->parent && item->parent->type == InterfaceItem)
00273         return item->parent->name;
00274     return QString();
00275 }
00276 
00277 QString QDBusModel::dBusMethodName(const QModelIndex &index) const
00278 {
00279     QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
00280     return item ? item->name : QString();
00281 }
00282 

Generated on Thu Mar 15 11:52:30 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1