#include "WidgetInspector.h"
#include "ObjectInspector.h"
#include "ObjectTreeModel.h"
#include "OutOfProcessClipboard.h"
#include "RootObjectList.h"
#include "WidgetInspectorShortcut.h"
#include "lib/DirectWidgetPicker.h"
#include "lib/WidgetPicker.h"
#include <QApplication>
#include <QClipboard>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSplitter>
#include <QTreeView>
#include <QVBoxLayout>
#include <QtDebug>
WidgetInspector::WidgetInspector(RootObjectList* rootList, QWidget* parent)
: QWidget(parent)
, m_rootList(rootList)
, m_picker(0)
, m_externalClipboard(new OutOfProcessClipboard(this))
{
setWindowTitle(tr("Widget Inspector"));
m_objectModel = new ObjectTreeModel(this);
m_objectTree = new QTreeView(this);
m_objectTree->header()->setVisible(false);
m_objectTree->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_objectTree->setModel(m_objectModel);
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
m_objectTree->header()->setSectionResizeMode(0,QHeaderView::ResizeToContents);
#else
m_objectTree->header()->setResizeMode(0,QHeaderView::ResizeToContents);
#endif
m_objectTree->header()->setStretchLastSection(false);
connect(m_objectTree->selectionModel(),SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this,SLOT(selectionChanged(QModelIndex,QModelIndex)));
m_objectInspector = new ObjectInspector(this);
QVBoxLayout* layout = new QVBoxLayout(this);
QSplitter* topSplitter = new QSplitter(this);
topSplitter->addWidget(m_objectTree);
topSplitter->addWidget(m_objectInspector);
layout->addWidget(topSplitter);
QHBoxLayout* searchLayout = new QHBoxLayout;
searchLayout->addWidget(new QLabel(tr("Search:"),this));
QLineEdit* searchEdit = new QLineEdit(this);
connect(searchEdit,SIGNAL(textChanged(QString)),this,SLOT(search(QString)));
searchLayout->addWidget(searchEdit);
layout->addLayout(searchLayout);
QPushButton* copyToDebuggerButton = new QPushButton(tr("Copy Reference"),this);
connect(copyToDebuggerButton,SIGNAL(clicked()),
this,SLOT(copyDebuggerReference()));
m_pickButton = new QPushButton(tr("Pick Widget"),this);
setWidgetPicker(new DirectWidgetPicker(this));
QPushButton* refreshButton = new QPushButton(tr("Refresh Tree"),this);
connect(refreshButton,SIGNAL(clicked()),this,SLOT(refreshTree()));
QPushButton* refreshObjectButton = new QPushButton(tr("Refresh Object"),this);
connect(refreshObjectButton,SIGNAL(clicked()),m_objectInspector,SLOT(refresh()));
QHBoxLayout* actionLayout = new QHBoxLayout;
actionLayout->addStretch();
actionLayout->addWidget(m_pickButton);
actionLayout->addWidget(copyToDebuggerButton);
actionLayout->addWidget(refreshButton);
actionLayout->addWidget(refreshObjectButton);
layout->addLayout(actionLayout);
resize(700,400);
refreshTree();
}
void WidgetInspector::pickerFinished(ObjectProxy::Pointer widget)
{
// TODO - Re-implement widget picker
select(widget);
}
void WidgetInspector::copyDebuggerReference()
{
ObjectProxy::Pointer object = m_objectInspector->object();
if (!object)
{
return;
}
void* address = reinterpret_cast<void*>(object->address());
QString reference = QString("(%1*)(%2)")
.arg(object->className())
.arg(ObjectInspector::formatAddress(address));
#ifdef Q_OS_LINUX
m_externalClipboard->setText(reference);
#else
QApplication::clipboard()->setText(reference);
#endif
}
void WidgetInspector::selectionChanged(const QModelIndex& current, const QModelIndex& previous)
{
Q_UNUSED(previous);
m_objectInspector->setObject(ObjectTreeModel::objectFromIndex(current));
}
void WidgetInspector::refreshTree()
{
QModelIndex current = m_objectTree->selectionModel()->currentIndex();
ObjectProxy::Pointer currentObject = ObjectTreeModel::objectFromIndex(current);
m_objectModel->setRootObjects(m_rootList->rootObjects());
if (currentObject)
{
select(currentObject);
}
}
void WidgetInspector::search(const QString& query)
{
QList<ObjectProxy::Pointer> results = m_objectModel->search(query);
if (!results.isEmpty())
{
select(results.first());
}
}
void WidgetInspector::select(ObjectProxy::Pointer object)
{
QModelIndex index = m_objectModel->index(object);
if (!index.isValid())
{
// if no matching object is found in the model, then try refreshing
// the model and searching again
refreshTree();
index = m_objectModel->index(object);
}
m_objectTree->scrollTo(index);
m_objectTree->selectionModel()->setCurrentIndex(index,QItemSelectionModel::SelectCurrent);
}
void WidgetInspector::registerGlobalShortcut(const QKeySequence& key, QWidget* parentWidget)
{
WidgetInspectorShortcut* shortcut = new WidgetInspectorShortcut(parentWidget);
shortcut->setKey(key);
shortcut->setContext(Qt::ApplicationShortcut);
}
void WidgetInspector::setWidgetPicker(WidgetPicker* picker)
{
delete m_picker;
picker->setParent(this);
m_picker = picker;
connect(m_picker,SIGNAL(widgetPicked(ObjectProxy::Pointer)),this,SLOT(pickerFinished(ObjectProxy::Pointer)));
connect(m_pickButton,SIGNAL(clicked()),m_picker,SLOT(start()));
}