tools/qdbus/qdbusviewer/qdbusviewer.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    67 QDBusViewer::QDBusViewer(const QDBusConnection &connection, QWidget *parent)  :
    67 QDBusViewer::QDBusViewer(const QDBusConnection &connection, QWidget *parent)  :
    68     QWidget(parent),
    68     QWidget(parent),
    69     c(connection),
    69     c(connection),
    70     objectPathRegExp(QLatin1String("\\[ObjectPath: (.*)\\]"))
    70     objectPathRegExp(QLatin1String("\\[ObjectPath: (.*)\\]"))
    71 {
    71 {
    72     services = new QTreeWidget;
    72     servicesModel = new QStringListModel(this);
    73     services->setRootIsDecorated(false);
    73     servicesFilterModel = new QSortFilterProxyModel(this);
    74     services->setHeaderLabels(QStringList(QLatin1String("Services")));
    74     servicesFilterModel->setSourceModel(servicesModel);
       
    75     servicesFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
       
    76     serviceFilterLine = new QLineEdit(this);
       
    77     serviceFilterLine->setPlaceholderText(tr("Search..."));
       
    78     servicesView = new QListView(this);
       
    79     servicesView->setModel(servicesFilterModel);
       
    80 
       
    81     connect(serviceFilterLine, SIGNAL(textChanged(QString)), servicesFilterModel, SLOT(setFilterFixedString(QString)));
    75 
    82 
    76     tree = new QTreeView;
    83     tree = new QTreeView;
    77     tree->setContextMenuPolicy(Qt::CustomContextMenu);
    84     tree->setContextMenuPolicy(Qt::CustomContextMenu);
    78 
    85 
    79     connect(tree, SIGNAL(activated(QModelIndex)), this, SLOT(activate(QModelIndex)));
    86     connect(tree, SIGNAL(activated(QModelIndex)), this, SLOT(activate(QModelIndex)));
    84     connect(refreshAction, SIGNAL(triggered()), this, SLOT(refreshChildren()));
    91     connect(refreshAction, SIGNAL(triggered()), this, SLOT(refreshChildren()));
    85 
    92 
    86     QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, tree);
    93     QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, tree);
    87     connect(refreshShortcut, SIGNAL(activated()), this, SLOT(refreshChildren()));
    94     connect(refreshShortcut, SIGNAL(activated()), this, SLOT(refreshChildren()));
    88 
    95 
    89     QVBoxLayout *topLayout = new QVBoxLayout(this);
    96     QVBoxLayout *layout = new QVBoxLayout(this);
       
    97     QSplitter *topSplitter = new QSplitter(Qt::Vertical, this);
       
    98     layout->addWidget(topSplitter);
       
    99 
    90     log = new QTextBrowser;
   100     log = new QTextBrowser;
    91     connect(log, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl)));
   101     connect(log, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl)));
    92 
   102 
    93     QHBoxLayout *layout = new QHBoxLayout;
   103     QSplitter *splitter = new QSplitter(topSplitter);
    94     layout->addWidget(services, 1);
   104     splitter->addWidget(servicesView);
    95     layout->addWidget(tree, 2);
   105 
    96 
   106     QWidget *servicesWidget = new QWidget;
    97     topLayout->addLayout(layout);
   107     QVBoxLayout *servicesLayout = new QVBoxLayout(servicesWidget);
    98     topLayout->addWidget(log);
   108     servicesLayout->addWidget(serviceFilterLine);
    99 
   109     servicesLayout->addWidget(servicesView);
   100     connect(services, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
   110     splitter->addWidget(servicesWidget);
   101             this, SLOT(serviceChanged(QTreeWidgetItem*)));
   111     splitter->addWidget(tree);
       
   112 
       
   113     topSplitter->addWidget(splitter);
       
   114     topSplitter->addWidget(log);
       
   115 
       
   116     connect(servicesView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
       
   117             this, SLOT(serviceChanged(QModelIndex)));
   102     connect(tree, SIGNAL(customContextMenuRequested(QPoint)),
   118     connect(tree, SIGNAL(customContextMenuRequested(QPoint)),
   103             this, SLOT(showContextMenu(QPoint)));
   119             this, SLOT(showContextMenu(QPoint)));
   104 
   120 
   105     QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
   121     QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
   106 
   122 
   131     log->append(QLatin1String("<font color=\"red\">Error: </font>") + Qt::escape(msg) + QLatin1String("<br>"));
   147     log->append(QLatin1String("<font color=\"red\">Error: </font>") + Qt::escape(msg) + QLatin1String("<br>"));
   132 }
   148 }
   133 
   149 
   134 void QDBusViewer::refresh()
   150 void QDBusViewer::refresh()
   135 {
   151 {
   136     services->clear();
   152     servicesModel->removeRows(0, servicesModel->rowCount());
   137 
   153 
   138     if (c.isConnected()) {
   154     if (c.isConnected()) {
   139         const QStringList serviceNames = c.interface()->registeredServiceNames();
   155         const QStringList serviceNames = c.interface()->registeredServiceNames();
   140         foreach (QString service, serviceNames)
   156         servicesModel->setStringList(serviceNames);
   141             new QTreeWidgetItem(services, QStringList(service));
       
   142     }
   157     }
   143 }
   158 }
   144 
   159 
   145 void QDBusViewer::activate(const QModelIndex &item)
   160 void QDBusViewer::activate(const QModelIndex &item)
   146 {
   161 {
   152     BusSignature sig;
   167     BusSignature sig;
   153     sig.mService = currentService;
   168     sig.mService = currentService;
   154     sig.mPath = model->dBusPath(item);
   169     sig.mPath = model->dBusPath(item);
   155     sig.mInterface = model->dBusInterface(item);
   170     sig.mInterface = model->dBusInterface(item);
   156     sig.mName = model->dBusMethodName(item);
   171     sig.mName = model->dBusMethodName(item);
       
   172     sig.mTypeSig = model->dBusTypeSignature(item);
   157 
   173 
   158     switch (model->itemType(item)) {
   174     switch (model->itemType(item)) {
   159     case QDBusModel::SignalItem:
   175     case QDBusModel::SignalItem:
   160         connectionRequested(sig);
   176         connectionRequested(sig);
   161         break;
   177         break;
   205     message.setArguments(arguments);
   221     message.setArguments(arguments);
   206     c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
   222     c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
   207 
   223 
   208 }
   224 }
   209 
   225 
       
   226 static QString getDbusSignature(const QMetaMethod& method)
       
   227 {
       
   228     // create a D-Bus type signature from QMetaMethod's parameters
       
   229     QString sig;
       
   230     for (int i = 0; i < method.parameterTypes().count(); ++i) {
       
   231         QVariant::Type type = QVariant::nameToType(method.parameterTypes().at(i));
       
   232         sig.append(QString::fromLatin1(QDBusMetaType::typeToSignature(type)));
       
   233     }
       
   234     return sig;
       
   235 }
       
   236 
   210 void QDBusViewer::callMethod(const BusSignature &sig)
   237 void QDBusViewer::callMethod(const BusSignature &sig)
   211 {
   238 {
   212     QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface, c);
   239     QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface, c);
   213     const QMetaObject *mo = iface.metaObject();
   240     const QMetaObject *mo = iface.metaObject();
   214 
   241 
   215     // find the method
   242     // find the method
   216     QMetaMethod method;
   243     QMetaMethod method;
   217     for (int i = 0; i < mo->methodCount(); ++i) {
   244     for (int i = 0; i < mo->methodCount(); ++i) {
   218         const QString signature = QString::fromLatin1(mo->method(i).signature());
   245         const QString signature = QString::fromLatin1(mo->method(i).signature());
   219         if (signature.startsWith(sig.mName) && signature.at(sig.mName.length()) == QLatin1Char('('))
   246         if (signature.startsWith(sig.mName) && signature.at(sig.mName.length()) == QLatin1Char('('))
   220             method = mo->method(i);
   247             if (getDbusSignature(mo->method(i)) == sig.mTypeSig)
       
   248                 method = mo->method(i);
   221     }
   249     }
   222     if (!method.signature()) {
   250     if (!method.signature()) {
   223         QMessageBox::warning(this, tr("Unable to find method"),
   251         QMessageBox::warning(this, tr("Unable to find method"),
   224                 tr("Unable to find method %1 on path %2 in interface %3").arg(
   252                 tr("Unable to find method %1 on path %2 in interface %3").arg(
   225                     sig.mName).arg(sig.mPath).arg(sig.mInterface));
   253                     sig.mName).arg(sig.mPath).arg(sig.mInterface));
   275     BusSignature sig;
   303     BusSignature sig;
   276     sig.mService = currentService;
   304     sig.mService = currentService;
   277     sig.mPath = model->dBusPath(item);
   305     sig.mPath = model->dBusPath(item);
   278     sig.mInterface = model->dBusInterface(item);
   306     sig.mInterface = model->dBusInterface(item);
   279     sig.mName = model->dBusMethodName(item);
   307     sig.mName = model->dBusMethodName(item);
       
   308     sig.mTypeSig = model->dBusTypeSignature(item);
   280 
   309 
   281     QMenu menu;
   310     QMenu menu;
   282     menu.addAction(refreshAction);
   311     menu.addAction(refreshAction);
   283 
   312 
   284     switch (model->itemType(item)) {
   313     switch (model->itemType(item)) {
   377     }
   406     }
   378 
   407 
   379     log->append(out);
   408     log->append(out);
   380 }
   409 }
   381 
   410 
   382 void QDBusViewer::serviceChanged(QTreeWidgetItem *item)
   411 void QDBusViewer::serviceChanged(const QModelIndex &index)
   383 {
   412 {
   384     delete tree->model();
   413     delete tree->model();
   385 
   414 
   386     currentService.clear();
   415     currentService.clear();
   387     if (!item)
   416     if (!index.isValid())
   388         return;
   417         return;
   389     currentService = item->text(0);
   418     currentService = index.data().toString();
   390 
   419 
   391     tree->setModel(new QDBusViewModel(currentService, c));
   420     tree->setModel(new QDBusViewModel(currentService, c));
   392     connect(tree->model(), SIGNAL(busError(QString)), this, SLOT(logError(QString)));
   421     connect(tree->model(), SIGNAL(busError(QString)), this, SLOT(logError(QString)));
   393 }
   422 }
   394 
   423 
   395 void QDBusViewer::serviceRegistered(const QString &service)
   424 void QDBusViewer::serviceRegistered(const QString &service)
   396 {
   425 {
   397     if (service == c.baseService())
   426     if (service == c.baseService())
   398         return;
   427         return;
   399 
   428 
   400     new QTreeWidgetItem(services, QStringList(service));
   429     servicesModel->insertRows(0, 1);
   401 }
   430     servicesModel->setData(servicesModel->index(0, 0), service);
   402 
   431 }
   403 static QTreeWidgetItem *findItem(const QTreeWidget *services, const QString &name)
   432 
   404 {
   433 static QModelIndex findItem(QStringListModel *servicesModel, const QString &name)
   405     for (int i = 0; i < services->topLevelItemCount(); ++i) {
   434 {
   406         if (services->topLevelItem(i)->text(0) == name)
   435     QModelIndexList hits = servicesModel->match(servicesModel->index(0, 0), Qt::DisplayRole, name);
   407             return services->topLevelItem(i);
   436     if (hits.isEmpty())
   408     }
   437         return QModelIndex();
   409     return 0;
   438 
       
   439     return hits.first();
   410 }
   440 }
   411 
   441 
   412 void QDBusViewer::serviceUnregistered(const QString &name)
   442 void QDBusViewer::serviceUnregistered(const QString &name)
   413 {
   443 {
   414     delete findItem(services, name);
   444     QModelIndex hit = findItem(servicesModel, name);
       
   445     if (!hit.isValid())
       
   446         return;
       
   447     servicesModel->removeRows(hit.row(), 1);
   415 }
   448 }
   416 
   449 
   417 void QDBusViewer::serviceOwnerChanged(const QString &name, const QString &oldOwner,
   450 void QDBusViewer::serviceOwnerChanged(const QString &name, const QString &oldOwner,
   418                                       const QString &newOwner)
   451                                       const QString &newOwner)
   419 {
   452 {
   420     QTreeWidgetItem *item = findItem(services, name);
   453     QModelIndex hit = findItem(servicesModel, name);
   421 
   454 
   422     if (!item && oldOwner.isEmpty() && !newOwner.isEmpty())
   455     if (!hit.isValid() && oldOwner.isEmpty() && !newOwner.isEmpty())
   423         serviceRegistered(name);
   456         serviceRegistered(name);
   424     else if (item && !oldOwner.isEmpty() && newOwner.isEmpty())
   457     else if (hit.isValid() && !oldOwner.isEmpty() && newOwner.isEmpty())
   425         delete item;
   458         servicesModel->removeRows(hit.row(), 1);
   426     else if (item && !oldOwner.isEmpty() && !newOwner.isEmpty()) {
   459     else if (hit.isValid() && !oldOwner.isEmpty() && !newOwner.isEmpty()) {
   427         delete item;
   460         servicesModel->removeRows(hit.row(), 1);
   428         serviceRegistered(name);
   461         serviceRegistered(name);
   429     }
   462     }
   430 }
   463 }
   431 
   464 
   432 void QDBusViewer::refreshChildren()
   465 void QDBusViewer::refreshChildren()