oopapidocs  2.0
qobjectbrowser.cpp
00001 /****************************************************************************
00002  This file is part of ChainLink
00003  Copyright (C) 2007 Jeremy Magland (Jeremy.Magland@gmail.com)
00004 
00005  ChainLink is free software; you can redistribute it and/or modify
00006  it under the terms of the GNU General Public License as published by
00007  the Free Software Foundation; either version 2 of the License, or
00008  (at your option) any later version.
00009 
00010  ChainLink is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  GNU General Public License for more details.
00014 
00015  You should have received a copy of the GNU General Public License
00016  along with ChainLink; if not, write to the Free Software
00017  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 *****************************************************************************/
00020 
00021 #include "qobjectbrowser.h"
00022 #include "ui_qobjectbrowser.h"
00023 #include <QVBoxLayout>
00024 #include <QHeaderView>
00025 #include <QToolBar>
00026 #include <QSettings>
00027 #include <QTimer>
00028 #include <stdio.h>
00029 
00030 
00031     QObjectBrowserControl::QObjectBrowserControl(QWidget *parent) : QWidget(parent),
00032     ui (new Ui_qobjectbrowser){
00033         ui->setupUi(this);
00034 
00035         m_obj=0;
00036 
00037         connect(ui->update_children_button,SIGNAL(clicked()),this,SLOT(on_update_children()));
00038         connect(ui->update_properties_button,SIGNAL(clicked()),this,SLOT(on_update_properties()));
00039         connect(ui->parent_button,SIGNAL(clicked()),this,SLOT(on_up_to_parent()));
00040 
00041         connect(ui->children_table,SIGNAL(cellDoubleClicked (int,int)),this,SLOT(on_children_table_cell_clicked(int,int)));
00042 
00043                 set_object(parent);
00044         }
00045         QObjectBrowserControl::~QObjectBrowserControl() {
00046         delete ui;
00047                 clear_signal_records();
00048         }
00049         void QObjectBrowserControl::clear() {
00050         ui->children_table->clearContents(); ui->children_table->setRowCount(1);
00051         ui->properties_table->clearContents(); ui->properties_table->setRowCount(1);
00052         ui->signals_table->clearContents(); ui->signals_table->setRowCount(1);
00053         ui->slots_table->clearContents(); ui->slots_table->setRowCount(1);
00054         ui->methods_table->clearContents(); ui->methods_table->setRowCount(1);
00055 
00056         ui->class_name->setText("");
00057         ui->base_class_name->setText("");
00058 
00059                 clear_signal_records();
00060 
00061                 repaint();
00062 
00063         }
00064 
00065         void QObjectBrowserControl::clear_signal_records() {
00066                 int j;
00067         for (j=0; j<m_signal_records.count(); j++)
00068             delete m_signal_records[j];
00069         m_signal_records.clear();
00070         }
00071         bool QObjectBrowserControl::hasdescendent(QObject *obj) {
00072                 while (obj) {
00073                         if (obj==this) return true;
00074                         obj=obj->parent();
00075                 }
00076                 return false;
00077         }
00078         void QObjectBrowserControl::on_object_destroyed() {
00079         m_obj=0;
00080                 clear();
00081         }
00082         void QObjectBrowserControl::set_object(QObject *obj_in) {
00083         if (m_obj) {
00084             disconnect(m_obj,SIGNAL(destroyed()),this,SLOT(on_object_destroyed()));
00085                 }
00086         m_obj=obj_in;
00087 
00088                 clear();
00089 
00090         if (!m_obj) return;
00091 
00092         connect(m_obj,SIGNAL(destroyed()),this,SLOT(on_object_destroyed()));
00093 
00094         const QMetaObject *metaobj=m_obj->metaObject();
00095                 if (!metaobj) return;
00096         ui->class_name->setText(metaobj->className());
00097                 if (metaobj->superClass())
00098             ui->base_class_name->setText(metaobj->superClass()->className());
00099                 else
00100             ui->base_class_name->setText("");
00101 
00102         if (m_obj->parent())
00103             ui->parent_button->setEnabled(true);
00104                 else
00105             ui->parent_button->setEnabled(false);
00106         if ((m_obj->parent())&&(m_obj->parent()->metaObject()))
00107             ui->parent_class_name->setText(m_obj->parent()->metaObject()->className());
00108                 else
00109             ui->parent_class_name->setText("");
00110 
00111                 set_children();
00112                 set_properties();
00113                 set_signals();
00114                 set_slots();
00115                 set_methods();
00116 
00117         emit object_changed(m_obj);
00118         }
00119         void QObjectBrowserControl::set_children() {
00120         ui->children_table->clear();
00121         ui->children_table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00122         ui->children_table->setColumnCount(2);
00123         ui->children_table->setHorizontalHeaderLabels(QStringList() << tr("Type") << tr("Name") );
00124 
00125         if (!m_obj) return;
00126 
00127         QObjectList objlist=m_obj->children();
00128 
00129         ui->children_table->setRowCount(objlist.count());
00130 
00131                 int j;
00132                 QTableWidgetItem *item;
00133                 for (j=0; j<objlist.count(); j++) {
00134                         QString txt="[   ]";
00135                         const QMetaObject *metaobj=objlist[j]->metaObject();
00136                         if (metaobj) {
00137                                 txt=metaobj->className();
00138                         }
00139 
00140                         item=new QTableWidgetItem;
00141                         item->setText(txt);
00142                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00143             ui->children_table->setItem(j,0,item);
00144 
00145                         item=new QTableWidgetItem;
00146                         item->setText(objlist[j]->objectName());
00147                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00148             ui->children_table->setItem(j,1,item);
00149 
00150                 }
00151         }
00152         void QObjectBrowserControl::set_properties() {
00153         ui->properties_table->clear();
00154         ui->properties_table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00155         ui->properties_table->setColumnCount(3);
00156         ui->properties_table->setHorizontalHeaderLabels(QStringList() << tr("Type") << tr("Name") << tr("Value"));
00157 
00158         if (!m_obj) return;
00159         const QMetaObject *metaobj=m_obj->metaObject();
00160                 if (!metaobj) return;
00161 
00162 
00163         ui->properties_table->setRowCount(metaobj->propertyCount());
00164 
00165                 int j;
00166                 QTableWidgetItem *item;
00167                 for (j=0; j<metaobj->propertyCount(); j++) {
00168                         QMetaProperty prop=metaobj->property(j);
00169 
00170                         item=new QTableWidgetItem;
00171                         item->setText(prop.typeName());
00172                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00173             ui->properties_table->setItem(j,0,item);
00174 
00175                         item=new QTableWidgetItem;
00176                         item->setText(prop.name());
00177                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00178             ui->properties_table->setItem(j,1,item);
00179 
00180                         item=new QTableWidgetItem;
00181             item->setText(prop.read(m_obj).toString());
00182                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00183             ui->properties_table->setItem(j,2,item);
00184                 }
00185         }
00186         void QObjectBrowserControl::set_signals() {
00187         ui->signals_table->clear();
00188                 clear_signal_records();
00189         ui->signals_table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00190         ui->signals_table->setColumnCount(2);
00191         ui->signals_table->setHorizontalHeaderLabels(QStringList() << tr("Signal") << tr("Count")); // << tr("Connects"));
00192 
00193         if (m_obj==(QObject *)ui->signals_table) {
00194                         //don't map the signals for the signal table, due to recursion
00195                         return;
00196                 }
00197 
00198         if (!m_obj) return;
00199         const QMetaObject *metaobj=m_obj->metaObject();
00200                 if (!metaobj) return;
00201 
00202                 int ct=0;
00203                 int j;
00204                 for (j=0; j<metaobj->methodCount(); j++)
00205                         if (metaobj->method(j).methodType()==QMetaMethod::Signal)
00206                                 ct++;
00207         ui->signals_table->setRowCount(ct);
00208 
00209                 QTableWidgetItem *item;
00210                 ct=0;
00211 
00212                 for (j=0; j<metaobj->methodCount(); j++) {
00213                         QMetaMethod meth=metaobj->method(j);
00214                         if (meth.methodType()==QMetaMethod::Signal) {
00215                                 QOB_signal_record *ptr=new QOB_signal_record;
00216                 ptr->m_sigmapper=new QSignalMapper;
00217                 ptr->m_sigmapper->setMapping(m_obj,ct);
00218                                 char holdstr[1000];
00219                                 sprintf(holdstr,"2%s",meth.signature());
00220                 connect(m_obj,holdstr,ptr->m_sigmapper,SLOT(map()));
00221                 connect(ptr->m_sigmapper,SIGNAL(mapped(int)),this,SLOT(on_signal_triggered(int)));
00222                 m_signal_records.append(ptr);
00223 
00224                                 item=new QTableWidgetItem;
00225                                 item->setText(meth.signature());
00226                                 item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00227                 ui->signals_table->setItem(ct,0,item);
00228                 // TODO: setItem (ct, 2, new item that shows the number of connections )
00229 
00230 
00231                                 ct++;
00232                         }
00233                 }
00234                 update_signal_values();
00235         }
00236         void QObjectBrowserControl::update_signal_values() {
00237         if (!m_obj) return;
00238         const QMetaObject *metaobj=m_obj->metaObject();
00239                 if (!metaobj) return;
00240 
00241                 int ct=0;
00242                 int j;
00243                 for (j=0; j<metaobj->methodCount(); j++) {
00244                         QMetaMethod meth=metaobj->method(j);
00245                         if (meth.methodType()==QMetaMethod::Signal) {
00246                                 update_signal_value(ct);
00247                                 ct++;
00248                         }
00249                 }
00250 
00251         }
00252         void QObjectBrowserControl::update_signal_value(int sig_num) {
00253                 QTableWidgetItem *item=new QTableWidgetItem;
00254         if ((sig_num>=0)&&(sig_num<m_signal_records.count())) {
00255             item->setText(QString::number(m_signal_records[sig_num]->m_count));
00256                         item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00257                 }
00258         ui->signals_table->setItem(sig_num,1,item);
00259 
00260 
00261 
00262         }
00263         void QObjectBrowserControl::set_slots() {
00264         ui->slots_table->clear();
00265         ui->slots_table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00266         ui->slots_table->setColumnCount(2);
00267         ui->slots_table->setHorizontalHeaderLabels(QStringList() << "Type" << "Slot");
00268 
00269         if (!m_obj) return;
00270         const QMetaObject *metaobj=m_obj->metaObject();
00271                 if (!metaobj) return;
00272 
00273                 int ct=0;
00274                 int j;
00275                 for (j=0; j<metaobj->methodCount(); j++)
00276                         if (metaobj->method(j).methodType()==QMetaMethod::Slot)
00277                                 ct++;
00278         ui->slots_table->setRowCount(ct);
00279 
00280                 ct=0;
00281                 QTableWidgetItem *item;
00282                 for (j=0; j<metaobj->methodCount(); j++) {
00283                         QMetaMethod meth=metaobj->method(j);
00284                         if (meth.methodType()==QMetaMethod::Slot) {
00285                                 item=new QTableWidgetItem;
00286 
00287                                 QString typeName = meth.typeName();
00288                                 if( typeName.isEmpty() )
00289                                         typeName = "void";
00290 
00291                                 item->setText(typeName);
00292                                 item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00293                 ui->slots_table->setItem(ct,0,item);
00294                                 item=new QTableWidgetItem;
00295                                 item->setText(meth.signature());
00296                                 item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00297                 ui->slots_table->setItem(ct,1,item);
00298 
00299                                 ct++;
00300                         }
00301                 }
00302         }
00303         void QObjectBrowserControl::set_methods() {
00304         ui->methods_table->clear();
00305         ui->methods_table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00306         ui->methods_table->setColumnCount(2);
00307         ui->methods_table->setHorizontalHeaderLabels(QStringList() << "Type" << "Slot");
00308 
00309         if (!m_obj) return;
00310         const QMetaObject *metaobj=m_obj->metaObject();
00311                 if (!metaobj) return;
00312 
00313                 int ct=0;
00314                 int j;
00315                 for (j=0; j<metaobj->methodCount(); j++)
00316                         if (metaobj->method(j).methodType()==QMetaMethod::Method)
00317                                 ct++;
00318         ui->methods_table->setRowCount(ct);
00319 
00320                 ct=0;
00321                 QTableWidgetItem *item;
00322                 for (j=0; j<metaobj->methodCount(); j++) {
00323                         QMetaMethod meth=metaobj->method(j);
00324                         if (meth.methodType()==QMetaMethod::Method) {
00325                                 item=new QTableWidgetItem;
00326                                 item->setText(meth.typeName());
00327                                 item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00328                 ui->methods_table->setItem(ct,0,item);
00329 
00330                                 item=new QTableWidgetItem;
00331                                 item->setText(meth.signature());
00332                                 item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00333                 ui->methods_table->setItem(ct,1,item);
00334 
00335                                 ct++;
00336                         }
00337                 }
00338         }
00339 
00340         void QObjectBrowserControl::on_signal_triggered(int signal_num) {
00341         if ((signal_num<0)||(signal_num>=m_signal_records.count()))
00342                         return;
00343         m_signal_records[signal_num]->m_count++;
00344                 update_signal_value(signal_num);
00345         }
00346         void QObjectBrowserControl::on_update_children() {
00347                 set_children();
00348         }
00349         void QObjectBrowserControl::on_update_properties() {
00350                 set_properties();
00351         }
00352         void QObjectBrowserControl::on_up_to_parent() {
00353         if ((m_obj)&&(m_obj->parent()))
00354             set_object(m_obj->parent());
00355         }
00356 
00357         void QObjectBrowserControl::on_children_table_cell_clicked(int row, int column) {
00358                 Q_UNUSED(column);
00359         if (!m_obj) return;
00360         QObjectList objlist=m_obj->children();
00361                 if (row<objlist.count()) {
00362                         set_object(objlist[row]);
00363                 }
00364         }
00365 
00366 
00367         QOB_signal_record::QOB_signal_record() {
00368         m_sigmapper=0;
00369         m_count=0;
00370         }
00371         QOB_signal_record::~QOB_signal_record() {
00372         if (m_sigmapper) delete m_sigmapper;
00373         m_sigmapper=0;
00374         }
00375 
00376     QObjectBrowser::QObjectBrowser(QWidget* parent) : QWidget(parent),
00377     m_control (new QObjectBrowserControl),
00378     m_tree (new QObjectTree) {
00379         m_last_focus_window=0;
00380         setObjectName("QObjectBrowser");
00381         setWindowTitle(tr("QObject Browser"));
00382 //              setWindowFlags(windowFlags()|Qt::WindowStaysOnTopHint);
00383 //              setWindowFlags(windowFlags()|Qt::WindowStaysOnTopHint|Qt::X11BypassWindowManagerHint);
00384 
00385         m_tree->setModel(&m_model);
00386         QVBoxLayout *layout = new QVBoxLayout(this);
00387         setLayout(layout);
00388         QToolBar *update_toolbar=new QToolBar(tr("Update"));
00389         layout->addWidget(update_toolbar);
00390 
00391                 QSplitter *splitter=new QSplitter(Qt::Horizontal,this);
00392         layout->addWidget(splitter);
00393         splitter->addWidget(m_tree.data());
00394         splitter->addWidget(m_control.data());
00395                 splitter->setStretchFactor(0,1);
00396                 splitter->setStretchFactor(1,0);
00397 
00398         m_tree->update();
00399 
00400                 QPushButton *update_button=new QPushButton(QString("Update"),this);
00401                 update_toolbar->addWidget(update_button);
00402                 connect(update_button, SIGNAL(clicked()), this, SLOT(on_update()));
00403 
00404         QPushButton *dump_button = new QPushButton(QString("DumpObject"), this);
00405         update_toolbar->addWidget(dump_button);
00406         connect(dump_button, SIGNAL(clicked()), this, SLOT(dumpObject()));
00407 
00408                 QPushButton *focus_button=new QPushButton(QString("Browse Focus Widget"),this);
00409                 update_toolbar->addWidget(focus_button);
00410                 connect(focus_button, SIGNAL(clicked()), this, SLOT(on_browse_focus()));
00411 
00412 
00413         connect(m_tree.data(),SIGNAL(show_widget()),this,SLOT(on_show_widget()));
00414         connect(m_tree.data(),SIGNAL(hide_widget()),this,SLOT(on_hide_widget()));
00415         connect(m_tree.data(),SIGNAL(focus_widget()),this,SLOT(on_focus_widget()));
00416         connect(m_tree.data(),SIGNAL(current_item_changed()),this,SLOT(on_current_item_changed()));
00417         connect(m_control.data(),SIGNAL(object_changed(QObject *)),this,SLOT(on_object_changed(QObject *)));
00418                 connect(qApp,SIGNAL(focusChanged ( QWidget *, QWidget *)),this,SLOT(on_focus_changed( QWidget *, QWidget *)));
00419 
00420                 QTimer *timer = new QTimer(this);
00421                 connect(timer, SIGNAL(timeout()), this, SLOT(on_update()));
00422                 //connect(timer, SIGNAL(timeout()), this, SLOT(on_current_item_changed()));
00423                 timer->start(3000);
00424         restoreSettings();
00425         }
00426 
00427     void QObjectBrowser::closeEvent(QCloseEvent * e) {
00428         saveSettings();
00429         emit hidden();
00430         QWidget::closeEvent(e);
00431     }
00432 
00433     void QObjectBrowser::saveSettings() {
00434         QSettings s;
00435         s.setValue("obrowser/geometry", geometry());
00436     }
00437 
00438     void QObjectBrowser::restoreSettings() {
00439         QSettings s;
00440         QRect geom = s.value("obrowser/geometry", geometry()).toRect();
00441         setGeometry(geom);
00442     }
00443 
00444         void QObjectBrowser::set_object(QObject *obj) {
00445         if (!m_model.find_item(m_model.rootItem,obj))  //object is not valid
00446             m_control->set_object(0);
00447                 else
00448             m_control->set_object(obj);
00449         }
00450 
00451         void QObjectBrowser::on_current_item_changed() {
00452         QModelIndex index=m_tree->currentIndex();
00453                 if (!index.isValid()) return;
00454                 QObjectTreeItem *item = static_cast<QObjectTreeItem*>(index.internalPointer());
00455                 if (!item) return;
00456         set_object(item->m_obj);
00457         }
00458         void QObjectBrowser::on_object_changed(QObject *obj) {
00459         QModelIndex index=m_model.getindex(obj);
00460         m_tree->setCurrentIndex(index);
00461         m_tree->scrollTo(index);
00462         }
00463         void QObjectBrowser::on_update() {
00464         m_model.refresh();
00465 
00466 
00467         }
00468         void QObjectBrowser::on_focus_changed( QWidget *old, QWidget *now) {
00469                 Q_UNUSED(old);
00470                 if (!now) return;
00471                 QWidget *ptr=now;
00472                 while (ptr) {
00473                         if (ptr==this) return;
00474                         ptr=ptr->parentWidget();
00475                 }
00476         m_last_focus_window=now;
00477         }
00478         void QObjectBrowser::on_browse_focus() {
00479         if (m_last_focus_window)
00480             set_object(m_last_focus_window);
00481                 else
00482                         set_object(qApp->focusWidget());
00483         }
00484 
00485         QObject *QObjectBrowser::get_current_object() {
00486         QModelIndex index=m_tree->currentIndex();
00487                 if (!index.isValid()) return 0;
00488                 QObjectTreeItem *item = static_cast<QObjectTreeItem*>(index.internalPointer());
00489                 if (!item) return 0;
00490         return item->m_obj;
00491         }
00492         
00493         void QObjectBrowser::on_show_widget() {
00494                 QObject *obj=get_current_object();
00495                 if (!obj) return;
00496                 if (!obj->isWidgetType()) return;
00497                 QWidget *W=(QWidget *)obj;
00498                 W->show();
00499         }
00500         
00501         void QObjectBrowser::on_hide_widget() {
00502                 QObject *obj=get_current_object();
00503                 if (!obj) return;
00504                 if (!obj->isWidgetType()) return;
00505                 QWidget *W=(QWidget *)obj;
00506                 W->hide();
00507         emit hidden();
00508         }
00509         void QObjectBrowser::on_focus_widget() {
00510                 QObject *obj=get_current_object();
00511                 if (!obj) return;
00512                 if (!obj->isWidgetType()) return;
00513                 QWidget *W=(QWidget *)obj;
00514                 W->activateWindow();
00515                 W->setFocus(Qt::ActiveWindowFocusReason);
00516         }
00517     void QObjectBrowser::dumpObject() {
00518             QObject *obj = get_current_object();
00519         obj->dumpObjectInfo();
00520     }
 All Classes Namespaces Functions Enumerations