forked from qt-creator/qt-creator
QmlJsInspector: implemented Property Inspector
Reviewed-by: Kai Koehne
This commit is contained in:
@@ -57,6 +57,9 @@ public:
|
|||||||
|
|
||||||
explicit CrumblePathButton(const QString &title, QWidget *parent = 0);
|
explicit CrumblePathButton(const QString &title, QWidget *parent = 0);
|
||||||
void setSegmentType(int type);
|
void setSegmentType(int type);
|
||||||
|
void select(bool s);
|
||||||
|
void setData(QVariant data);
|
||||||
|
QVariant data() const;
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *);
|
void paintEvent(QPaintEvent *);
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
@@ -70,6 +73,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
bool m_isHovering;
|
bool m_isHovering;
|
||||||
bool m_isPressed;
|
bool m_isPressed;
|
||||||
|
bool m_isSelected;
|
||||||
bool m_isEnd;
|
bool m_isEnd;
|
||||||
QColor m_baseColor;
|
QColor m_baseColor;
|
||||||
QImage m_segment;
|
QImage m_segment;
|
||||||
@@ -79,10 +83,12 @@ private:
|
|||||||
QImage m_segmentHover;
|
QImage m_segmentHover;
|
||||||
QImage m_segmentHoverEnd;
|
QImage m_segmentHoverEnd;
|
||||||
QPoint m_textPos;
|
QPoint m_textPos;
|
||||||
|
|
||||||
|
QVariant m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
CrumblePathButton::CrumblePathButton(const QString &title, QWidget *parent)
|
CrumblePathButton::CrumblePathButton(const QString &title, QWidget *parent)
|
||||||
: QPushButton(title, parent), m_isHovering(false), m_isPressed(false), m_isEnd(true)
|
: QPushButton(title, parent), m_isHovering(false), m_isPressed(false), m_isSelected(false), m_isEnd(true)
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||||
setToolTip(title);
|
setToolTip(title);
|
||||||
@@ -114,7 +120,7 @@ void CrumblePathButton::paintEvent(QPaintEvent *)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_isEnd) {
|
if (m_isEnd) {
|
||||||
if (m_isPressed) {
|
if (m_isPressed || m_isSelected) {
|
||||||
Utils::StyleHelper::drawCornerImage(m_segmentSelectedEnd, &p, geom, 2, 0, 2, 0);
|
Utils::StyleHelper::drawCornerImage(m_segmentSelectedEnd, &p, geom, 2, 0, 2, 0);
|
||||||
} else if (m_isHovering) {
|
} else if (m_isHovering) {
|
||||||
Utils::StyleHelper::drawCornerImage(m_segmentHoverEnd, &p, geom, 2, 0, 2, 0);
|
Utils::StyleHelper::drawCornerImage(m_segmentHoverEnd, &p, geom, 2, 0, 2, 0);
|
||||||
@@ -122,7 +128,7 @@ void CrumblePathButton::paintEvent(QPaintEvent *)
|
|||||||
Utils::StyleHelper::drawCornerImage(m_segmentEnd, &p, geom, 2, 0, 2, 0);
|
Utils::StyleHelper::drawCornerImage(m_segmentEnd, &p, geom, 2, 0, 2, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m_isPressed) {
|
if (m_isPressed || m_isSelected) {
|
||||||
Utils::StyleHelper::drawCornerImage(m_segmentSelected, &p, geom, 2, 0, 12, 0);
|
Utils::StyleHelper::drawCornerImage(m_segmentSelected, &p, geom, 2, 0, 12, 0);
|
||||||
} else if (m_isHovering) {
|
} else if (m_isHovering) {
|
||||||
Utils::StyleHelper::drawCornerImage(m_segmentHover, &p, geom, 2, 0, 12, 0);
|
Utils::StyleHelper::drawCornerImage(m_segmentHover, &p, geom, 2, 0, 12, 0);
|
||||||
@@ -175,6 +181,12 @@ void CrumblePathButton::mouseReleaseEvent(QMouseEvent *e)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrumblePathButton::select(bool s)
|
||||||
|
{
|
||||||
|
m_isSelected = s;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void CrumblePathButton::setSegmentType(int type)
|
void CrumblePathButton::setSegmentType(int type)
|
||||||
{
|
{
|
||||||
bool useLeftPadding = !(type & FirstSegment);
|
bool useLeftPadding = !(type & FirstSegment);
|
||||||
@@ -182,6 +194,16 @@ void CrumblePathButton::setSegmentType(int type)
|
|||||||
m_textPos.setX(useLeftPadding ? 18 : 4);
|
m_textPos.setX(useLeftPadding ? 18 : 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrumblePathButton::setData(QVariant data)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CrumblePathButton::data() const
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
struct CrumblePathPrivate {
|
struct CrumblePathPrivate {
|
||||||
explicit CrumblePathPrivate(CrumblePath *q);
|
explicit CrumblePathPrivate(CrumblePath *q);
|
||||||
|
|
||||||
@@ -216,12 +238,25 @@ CrumblePath::~CrumblePath()
|
|||||||
d->m_buttons.clear();
|
d->m_buttons.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrumblePath::selectIndex(int index)
|
||||||
|
{
|
||||||
|
if ((index > -1) && (index < d->m_buttons.length()))
|
||||||
|
d->m_buttons[index]->select(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CrumblePath::dataForIndex(int index) const
|
||||||
|
{
|
||||||
|
if ((index > -1) && (index < d->m_buttons.length()))
|
||||||
|
return d->m_buttons[index]->data();
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
void CrumblePath::setBackgroundStyle()
|
void CrumblePath::setBackgroundStyle()
|
||||||
{
|
{
|
||||||
d->m_background->setStyleSheet("QWidget { background-color:" + d->m_baseColor.name() + ";}");
|
d->m_background->setStyleSheet("QWidget { background-color:" + d->m_baseColor.name() + ";}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrumblePath::pushElement(const QString &title)
|
void CrumblePath::pushElement(const QString &title, const QVariant data)
|
||||||
{
|
{
|
||||||
CrumblePathButton *newButton = new CrumblePathButton(title, this);
|
CrumblePathButton *newButton = new CrumblePathButton(title, this);
|
||||||
newButton->hide();
|
newButton->hide();
|
||||||
@@ -237,6 +272,7 @@ void CrumblePath::pushElement(const QString &title)
|
|||||||
segType = CrumblePathButton::FirstSegment | CrumblePathButton::LastSegment;
|
segType = CrumblePathButton::FirstSegment | CrumblePathButton::LastSegment;
|
||||||
newButton->setSegmentType(segType);
|
newButton->setSegmentType(segType);
|
||||||
}
|
}
|
||||||
|
newButton->setData(data);
|
||||||
d->m_buttons.append(newButton);
|
d->m_buttons.append(newButton);
|
||||||
|
|
||||||
resizeButtons();
|
resizeButtons();
|
||||||
@@ -272,8 +308,6 @@ void CrumblePath::resizeEvent(QResizeEvent *)
|
|||||||
|
|
||||||
void CrumblePath::resizeButtons()
|
void CrumblePath::resizeButtons()
|
||||||
{
|
{
|
||||||
int buttonMinWidth = 0;
|
|
||||||
int buttonMaxWidth = 0;
|
|
||||||
int totalWidthLeft = width();
|
int totalWidthLeft = width();
|
||||||
|
|
||||||
if (d->m_buttons.length() >= 1) {
|
if (d->m_buttons.length() >= 1) {
|
||||||
@@ -281,26 +315,34 @@ void CrumblePath::resizeButtons()
|
|||||||
|
|
||||||
d->m_buttons[0]->raise();
|
d->m_buttons[0]->raise();
|
||||||
// rearrange all items so that the first item is on top (added last).
|
// rearrange all items so that the first item is on top (added last).
|
||||||
|
|
||||||
|
// compute relative sizes
|
||||||
|
QList <int> sizes;
|
||||||
|
int totalSize = 0;
|
||||||
for(int i = 0; i < d->m_buttons.length() ; ++i) {
|
for(int i = 0; i < d->m_buttons.length() ; ++i) {
|
||||||
CrumblePathButton *button = d->m_buttons[i];
|
CrumblePathButton *button = d->m_buttons[i];
|
||||||
|
|
||||||
QFontMetrics fm(button->font());
|
QFontMetrics fm(button->font());
|
||||||
buttonMinWidth = ArrowBorderSize + fm.width(button->text()) + ArrowBorderSize * 2 ;
|
int originalSize = ArrowBorderSize + fm.width(button->text()) + ArrowBorderSize + 12;
|
||||||
buttonMaxWidth = (totalWidthLeft + ArrowBorderSize * (d->m_buttons.length() - i)) / (d->m_buttons.length() - i);
|
sizes << originalSize;
|
||||||
|
totalSize += originalSize - ArrowBorderSize;
|
||||||
|
}
|
||||||
|
|
||||||
if (buttonMinWidth > buttonMaxWidth && i < d->m_buttons.length() - 1) {
|
for (int i = 0; i < d->m_buttons.length() ; ++i) {
|
||||||
buttonMinWidth = buttonMaxWidth;
|
CrumblePathButton *button = d->m_buttons[i];
|
||||||
} else if (i > 3 && (i == d->m_buttons.length() - 1)) {
|
|
||||||
buttonMinWidth = width() - nextElementPosition.x();
|
|
||||||
buttonMaxWidth = buttonMinWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
button->setMinimumWidth(buttonMinWidth);
|
int candidateSize = (sizes[i]*totalWidthLeft)/totalSize;
|
||||||
button->setMaximumWidth(buttonMaxWidth);
|
if (candidateSize < ArrowBorderSize)
|
||||||
|
candidateSize = ArrowBorderSize;
|
||||||
|
if (candidateSize > sizes[i]*1.3)
|
||||||
|
candidateSize = sizes[i]*1.3;
|
||||||
|
|
||||||
|
|
||||||
|
button->setMinimumWidth(candidateSize);
|
||||||
|
button->setMaximumWidth(candidateSize);
|
||||||
button->move(nextElementPosition);
|
button->move(nextElementPosition);
|
||||||
|
|
||||||
nextElementPosition.rx() += button->width() - ArrowBorderSize;
|
nextElementPosition.rx() += button->width() - ArrowBorderSize;
|
||||||
totalWidthLeft -= button->width();
|
|
||||||
|
|
||||||
button->show();
|
button->show();
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
#include <QtGui/QWidget>
|
#include <QtGui/QWidget>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QResizeEvent)
|
QT_FORWARD_DECLARE_CLASS(QResizeEvent)
|
||||||
|
|
||||||
@@ -50,9 +51,11 @@ class QTCREATOR_UTILS_EXPORT CrumblePath : public QWidget
|
|||||||
public:
|
public:
|
||||||
explicit CrumblePath(QWidget *parent = 0);
|
explicit CrumblePath(QWidget *parent = 0);
|
||||||
~CrumblePath();
|
~CrumblePath();
|
||||||
|
void selectIndex(int index);
|
||||||
|
QVariant dataForIndex(int index) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void pushElement(const QString &title);
|
void pushElement(const QString &title, const QVariant data = QVariant());
|
||||||
void popElement();
|
void popElement();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
|||||||
@@ -1054,22 +1054,6 @@ protected:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool hasVisualPresentation(Node *ast)
|
|
||||||
{
|
|
||||||
Bind *bind = m_lookupContext->document()->bind();
|
|
||||||
const Interpreter::ObjectValue *objValue = bind->findQmlObject(ast);
|
|
||||||
if (!objValue)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QStringList prototypes;
|
|
||||||
foreach (const Interpreter::ObjectValue *value,
|
|
||||||
Interpreter::PrototypeIterator(objValue, m_lookupContext->context()).all()) {
|
|
||||||
prototypes.append(value->className());
|
|
||||||
}
|
|
||||||
|
|
||||||
return prototypes.contains(QString("QGraphicsObject"));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isIdBinding(UiObjectMember *member) const
|
inline bool isIdBinding(UiObjectMember *member) const
|
||||||
{
|
{
|
||||||
if (UiScriptBinding *script = cast<UiScriptBinding *>(member)) {
|
if (UiScriptBinding *script = cast<UiScriptBinding *>(member)) {
|
||||||
@@ -1116,7 +1100,7 @@ protected:
|
|||||||
if ((isRangeSelected() && intersectsCursor(begin, end))
|
if ((isRangeSelected() && intersectsCursor(begin, end))
|
||||||
|| (!isRangeSelected() && containsCursor(begin, end)))
|
|| (!isRangeSelected() && containsCursor(begin, end)))
|
||||||
{
|
{
|
||||||
if (initializer(member) && isSelectable(member) && hasVisualPresentation(member)) {
|
if (initializer(member) && isSelectable(member)) {
|
||||||
m_selectedMembers << member;
|
m_selectedMembers << member;
|
||||||
// move start towards end; this facilitates multiselection so that root is usually ignored.
|
// move start towards end; this facilitates multiselection so that root is usually ignored.
|
||||||
m_cursorPositionStart = qMin(end, m_cursorPositionEnd);
|
m_cursorPositionStart = qMin(end, m_cursorPositionEnd);
|
||||||
|
|||||||
@@ -43,13 +43,13 @@
|
|||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
#include <utils/styledbar.h>
|
#include <utils/styledbar.h>
|
||||||
#include <utils/filterlineedit.h>
|
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
namespace QmlJSInspector {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -78,6 +78,7 @@ QmlInspectorToolbar::QmlInspectorToolbar(QObject *parent) :
|
|||||||
m_menuPauseAction(0),
|
m_menuPauseAction(0),
|
||||||
m_playIcon(QIcon(QLatin1String(":/qml/images/play-small.png"))),
|
m_playIcon(QIcon(QLatin1String(":/qml/images/play-small.png"))),
|
||||||
m_pauseIcon(QIcon(QLatin1String(":/qml/images/pause-small.png"))),
|
m_pauseIcon(QIcon(QLatin1String(":/qml/images/pause-small.png"))),
|
||||||
|
m_filterExp(0),
|
||||||
m_colorBox(0),
|
m_colorBox(0),
|
||||||
m_emitSignals(true),
|
m_emitSignals(true),
|
||||||
m_isRunning(false),
|
m_isRunning(false),
|
||||||
@@ -98,6 +99,7 @@ void QmlInspectorToolbar::setEnabled(bool value)
|
|||||||
m_zoomAction->setEnabled(value);
|
m_zoomAction->setEnabled(value);
|
||||||
m_colorPickerAction->setEnabled(value);
|
m_colorPickerAction->setEnabled(value);
|
||||||
m_colorBox->setEnabled(value);
|
m_colorBox->setEnabled(value);
|
||||||
|
m_filterExp->setEnabled(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlInspectorToolbar::enable()
|
void QmlInspectorToolbar::enable()
|
||||||
@@ -295,6 +297,10 @@ void QmlInspectorToolbar::createActions(const Core::Context &context)
|
|||||||
m_colorBox->setInnerBorderColor(QColor(192,192,192));
|
m_colorBox->setInnerBorderColor(QColor(192,192,192));
|
||||||
m_colorBox->setOuterBorderColor(QColor(58,58,58));
|
m_colorBox->setOuterBorderColor(QColor(58,58,58));
|
||||||
configBarLayout->addWidget(m_colorBox);
|
configBarLayout->addWidget(m_colorBox);
|
||||||
|
|
||||||
|
m_filterExp = new QLineEdit(m_barWidget);
|
||||||
|
m_filterExp->setPlaceholderText("<filter property list>");
|
||||||
|
configBarLayout->addWidget(m_filterExp);
|
||||||
configBarLayout->addStretch();
|
configBarLayout->addStretch();
|
||||||
|
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
@@ -307,6 +313,7 @@ void QmlInspectorToolbar::createActions(const Core::Context &context)
|
|||||||
connect(m_selectAction, SIGNAL(triggered()), SLOT(activateSelectToolOnClick()));
|
connect(m_selectAction, SIGNAL(triggered()), SLOT(activateSelectToolOnClick()));
|
||||||
connect(m_zoomAction, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
|
connect(m_zoomAction, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
|
||||||
connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
|
connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
|
||||||
|
connect(m_filterExp, SIGNAL(textChanged(QString)), SIGNAL(filterTextChanged(QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *QmlInspectorToolbar::widget() const
|
QWidget *QmlInspectorToolbar::widget() const
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
QT_FORWARD_DECLARE_CLASS(QAction)
|
QT_FORWARD_DECLARE_CLASS(QAction)
|
||||||
QT_FORWARD_DECLARE_CLASS(QColor)
|
QT_FORWARD_DECLARE_CLASS(QColor)
|
||||||
QT_FORWARD_DECLARE_CLASS(QToolButton)
|
QT_FORWARD_DECLARE_CLASS(QToolButton)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QLineEdit)
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class Context;
|
class Context;
|
||||||
@@ -98,6 +99,7 @@ signals:
|
|||||||
|
|
||||||
void showAppOnTopSelected(bool isChecked);
|
void showAppOnTopSelected(bool isChecked);
|
||||||
void animationSpeedChanged(qreal slowdownFactor = 1.0f);
|
void animationSpeedChanged(qreal slowdownFactor = 1.0f);
|
||||||
|
void filterTextChanged(const QString &);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void activateDesignModeOnClick();
|
void activateDesignModeOnClick();
|
||||||
@@ -140,6 +142,8 @@ private:
|
|||||||
QIcon m_playIcon;
|
QIcon m_playIcon;
|
||||||
QIcon m_pauseIcon;
|
QIcon m_pauseIcon;
|
||||||
|
|
||||||
|
QLineEdit *m_filterExp;
|
||||||
|
|
||||||
ToolBarColorBox *m_colorBox;
|
ToolBarColorBox *m_colorBox;
|
||||||
|
|
||||||
bool m_emitSignals;
|
bool m_emitSignals;
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ void ClientProxy::disconnectFromServer()
|
|||||||
qDeleteAll(m_objectTreeQuery);
|
qDeleteAll(m_objectTreeQuery);
|
||||||
m_objectTreeQuery.clear();
|
m_objectTreeQuery.clear();
|
||||||
|
|
||||||
|
removeAllObjectWatches();
|
||||||
|
|
||||||
updateConnected();
|
updateConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +228,7 @@ QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId,
|
|||||||
if (objectRef.debugId() == debugId)
|
if (objectRef.debugId() == debugId)
|
||||||
return objectRef;
|
return objectRef;
|
||||||
|
|
||||||
foreach(const QDeclarativeDebugObjectReference &child, objectRef.children()) {
|
foreach (const QDeclarativeDebugObjectReference &child, objectRef.children()) {
|
||||||
QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, child);
|
QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, child);
|
||||||
if (result.debugId() == debugId)
|
if (result.debugId() == debugId)
|
||||||
return result;
|
return result;
|
||||||
@@ -261,7 +263,7 @@ QDeclarativeDebugObjectReference ClientProxy::objectReferenceForLocation(const i
|
|||||||
QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences() const
|
QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences() const
|
||||||
{
|
{
|
||||||
QList<QDeclarativeDebugObjectReference> result;
|
QList<QDeclarativeDebugObjectReference> result;
|
||||||
foreach(const QDeclarativeDebugObjectReference &it, m_rootObjects) {
|
foreach (const QDeclarativeDebugObjectReference &it, m_rootObjects) {
|
||||||
result.append(objectReferences(it));
|
result.append(objectReferences(it));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -272,7 +274,7 @@ QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QDec
|
|||||||
QList<QDeclarativeDebugObjectReference> result;
|
QList<QDeclarativeDebugObjectReference> result;
|
||||||
result.append(objectRef);
|
result.append(objectRef);
|
||||||
|
|
||||||
foreach(const QDeclarativeDebugObjectReference &child, objectRef.children()) {
|
foreach (const QDeclarativeDebugObjectReference &child, objectRef.children()) {
|
||||||
result.append(objectReferences(child));
|
result.append(objectReferences(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,6 +333,64 @@ void ClientProxy::clearComponentCache()
|
|||||||
m_observerClient->clearComponentCache();
|
m_observerClient->clearComponentCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClientProxy::addObjectWatch(int objectDebugId)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << "addObjectWatch():" << objectDebugId;
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// already set
|
||||||
|
if (m_objectWatches.keys().contains(objectDebugId))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QDeclarativeDebugObjectReference ref = objectReferenceForId(objectDebugId);
|
||||||
|
if (ref.debugId() != objectDebugId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QDeclarativeDebugWatch *watch = m_engineClient->addWatch(ref, this);
|
||||||
|
m_objectWatches.insert(objectDebugId, watch);
|
||||||
|
|
||||||
|
connect(watch,SIGNAL(valueChanged(QByteArray,QVariant)),this,SLOT(objectWatchTriggered(QByteArray,QVariant)));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientProxy::objectWatchTriggered(const QByteArray &propertyName, const QVariant &propertyValue)
|
||||||
|
{
|
||||||
|
QDeclarativeDebugWatch *watch = dynamic_cast<QDeclarativeDebugWatch *>(QObject::sender());
|
||||||
|
if (watch)
|
||||||
|
emit propertyChanged(watch->objectDebugId(),propertyName, propertyValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientProxy::removeObjectWatch(int objectDebugId)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug() << "removeObjectWatch():" << objectDebugId;
|
||||||
|
if (objectDebugId == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!m_objectWatches.keys().contains(objectDebugId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QDeclarativeDebugWatch *watch = m_objectWatches.value(objectDebugId);
|
||||||
|
disconnect(watch,SIGNAL(valueChanged(QByteArray,QVariant)), this, SLOT(objectWatchTriggered(QByteArray,QVariant)));
|
||||||
|
m_engineClient->removeWatch(watch);
|
||||||
|
delete watch;
|
||||||
|
m_objectWatches.remove(objectDebugId);
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientProxy::removeAllObjectWatches()
|
||||||
|
{
|
||||||
|
foreach (int watchedObject, m_objectWatches.keys())
|
||||||
|
removeObjectWatch(watchedObject);
|
||||||
|
Q_ASSERT(m_objectWatches.count() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
void ClientProxy::queryEngineContext(int id)
|
void ClientProxy::queryEngineContext(int id)
|
||||||
{
|
{
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
@@ -403,7 +463,7 @@ void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state)
|
|||||||
int old_count = m_debugIdHash.count();
|
int old_count = m_debugIdHash.count();
|
||||||
m_debugIdHash.clear();
|
m_debugIdHash.clear();
|
||||||
m_debugIdHash.reserve(old_count + 1);
|
m_debugIdHash.reserve(old_count + 1);
|
||||||
foreach(const QDeclarativeDebugObjectReference &it, m_rootObjects)
|
foreach (const QDeclarativeDebugObjectReference &it, m_rootObjects)
|
||||||
buildDebugIdHashRecursive(it);
|
buildDebugIdHashRecursive(it);
|
||||||
emit objectTreeUpdated();
|
emit objectTreeUpdated();
|
||||||
|
|
||||||
@@ -445,7 +505,7 @@ void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReferen
|
|||||||
// append the debug ids in the hash
|
// append the debug ids in the hash
|
||||||
m_debugIdHash[qMakePair<QString, int>(filename, rev)][qMakePair<int, int>(lineNum, colNum)].append(ref.debugId());
|
m_debugIdHash[qMakePair<QString, int>(filename, rev)][qMakePair<int, int>(lineNum, colNum)].append(ref.debugId());
|
||||||
|
|
||||||
foreach(const QDeclarativeDebugObjectReference &it, ref.children())
|
foreach (const QDeclarativeDebugObjectReference &it, ref.children())
|
||||||
buildDebugIdHashRecursive(it);
|
buildDebugIdHashRecursive(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ public:
|
|||||||
QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent=0);
|
QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent=0);
|
||||||
void clearComponentCache();
|
void clearComponentCache();
|
||||||
|
|
||||||
|
bool addObjectWatch(int objectDebugId);
|
||||||
|
bool removeObjectWatch(int objectDebugId);
|
||||||
|
void removeAllObjectWatches();
|
||||||
|
|
||||||
// returns the object references
|
// returns the object references
|
||||||
QList<QDeclarativeDebugObjectReference> objectReferences() const;
|
QList<QDeclarativeDebugObjectReference> objectReferences() const;
|
||||||
QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const;
|
QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const;
|
||||||
@@ -108,6 +112,7 @@ signals:
|
|||||||
void serverReloaded();
|
void serverReloaded();
|
||||||
void selectedColorChanged(const QColor &color);
|
void selectedColorChanged(const QColor &color);
|
||||||
void contextPathUpdated(const QStringList &contextPath);
|
void contextPathUpdated(const QStringList &contextPath);
|
||||||
|
void propertyChanged(int debugId, const QByteArray &propertyName, const QVariant &propertyValue);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshObjectTree();
|
void refreshObjectTree();
|
||||||
@@ -139,6 +144,7 @@ private slots:
|
|||||||
void objectTreeFetched(QDeclarativeDebugQuery::State state = QDeclarativeDebugQuery::Completed);
|
void objectTreeFetched(QDeclarativeDebugQuery::State state = QDeclarativeDebugQuery::Completed);
|
||||||
void fetchContextObjectRecursive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context);
|
void fetchContextObjectRecursive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context);
|
||||||
void newObjects();
|
void newObjects();
|
||||||
|
void objectWatchTriggered(const QByteArray &propertyName, const QVariant &propertyValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateConnected();
|
void updateConnected();
|
||||||
@@ -164,6 +170,8 @@ private:
|
|||||||
QTimer m_requestObjectsTimer;
|
QTimer m_requestObjectsTimer;
|
||||||
DebugIdHash m_debugIdHash;
|
DebugIdHash m_debugIdHash;
|
||||||
|
|
||||||
|
QHash<int, QDeclarativeDebugWatch *> m_objectWatches;
|
||||||
|
|
||||||
bool m_isConnected;
|
bool m_isConnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ ContextCrumblePath::ContextCrumblePath(QWidget *parent)
|
|||||||
: CrumblePath(parent), m_isEmpty(true)
|
: CrumblePath(parent), m_isEmpty(true)
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
updateContextPath(QStringList());
|
updateContextPath(QStringList(),QList<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextCrumblePath::~ContextCrumblePath()
|
ContextCrumblePath::~ContextCrumblePath()
|
||||||
@@ -50,11 +50,14 @@ ContextCrumblePath::~ContextCrumblePath()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextCrumblePath::updateContextPath(const QStringList &path)
|
void ContextCrumblePath::updateContextPath(const QStringList &path, const QList<int> &debugIds)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(path.count() == debugIds.count());
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
foreach(const QString &pathPart, path) {
|
|
||||||
pushElement(pathPart);
|
for (int i=0; i<path.count(); i++) {
|
||||||
|
pushElement(path[i],QVariant(debugIds[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isEmpty = path.isEmpty();
|
m_isEmpty = path.isEmpty();
|
||||||
@@ -63,10 +66,20 @@ void ContextCrumblePath::updateContextPath(const QStringList &path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContextCrumblePath::selectIndex(int index)
|
||||||
|
{
|
||||||
|
CrumblePath::selectIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
bool ContextCrumblePath::isEmpty() const
|
bool ContextCrumblePath::isEmpty() const
|
||||||
{
|
{
|
||||||
return m_isEmpty;
|
return m_isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ContextCrumblePath::debugIdForIndex(int index) const
|
||||||
|
{
|
||||||
|
return CrumblePath::dataForIndex(index).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlJSInspector
|
} // namespace QmlJSInspector
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ public:
|
|||||||
ContextCrumblePath(QWidget *parent = 0);
|
ContextCrumblePath(QWidget *parent = 0);
|
||||||
virtual ~ContextCrumblePath();
|
virtual ~ContextCrumblePath();
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
int debugIdForIndex(int index) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateContextPath(const QStringList &path);
|
void updateContextPath(const QStringList &path, const QList<int> &debugIds);
|
||||||
|
void selectIndex(int index);
|
||||||
private:
|
private:
|
||||||
bool m_isEmpty;
|
bool m_isEmpty;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#include "qmljsprivateapi.h"
|
#include "qmljsprivateapi.h"
|
||||||
#include "qmljscontextcrumblepath.h"
|
#include "qmljscontextcrumblepath.h"
|
||||||
#include "qmljsinspectorsettings.h"
|
#include "qmljsinspectorsettings.h"
|
||||||
#include "qmljsobjecttree.h"
|
#include "qmljspropertyinspector.h"
|
||||||
|
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
#include <qmljs/qmljsdocument.h>
|
#include <qmljs/qmljsdocument.h>
|
||||||
@@ -126,13 +126,13 @@ InspectorUi::InspectorUi(QObject *parent)
|
|||||||
, m_listeningToEditorManager(false)
|
, m_listeningToEditorManager(false)
|
||||||
, m_toolbar(0)
|
, m_toolbar(0)
|
||||||
, m_crumblePath(0)
|
, m_crumblePath(0)
|
||||||
, m_objectTreeWidget(0)
|
, m_propertyInspector(0)
|
||||||
, m_settings(new InspectorSettings(this))
|
, m_settings(new InspectorSettings(this))
|
||||||
, m_clientProxy(0)
|
, m_clientProxy(0)
|
||||||
, m_qmlEngine(0)
|
, m_qmlEngine(0)
|
||||||
, m_debugQuery(0)
|
, m_debugQuery(0)
|
||||||
, m_lastSelectedDebugId(-1)
|
|
||||||
, m_debugProject(0)
|
, m_debugProject(0)
|
||||||
|
, m_selectionCallbackExpected(false)
|
||||||
{
|
{
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
m_toolbar = new QmlInspectorToolbar(this);
|
m_toolbar = new QmlInspectorToolbar(this);
|
||||||
@@ -225,7 +225,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
|
|||||||
if ((qmlNode->kind == QmlJS::AST::Node::Kind_IdentifierExpression) &&
|
if ((qmlNode->kind == QmlJS::AST::Node::Kind_IdentifierExpression) &&
|
||||||
(m_clientProxy->objectReferenceForId(refToLook).debugId() == -1)) {
|
(m_clientProxy->objectReferenceForId(refToLook).debugId() == -1)) {
|
||||||
query = doubleQuote + QString("local: ") + refToLook + doubleQuote;
|
query = doubleQuote + QString("local: ") + refToLook + doubleQuote;
|
||||||
foreach(QDeclarativeDebugPropertyReference property, ref.properties()) {
|
foreach (QDeclarativeDebugPropertyReference property, ref.properties()) {
|
||||||
if (property.name() == wordAtCursor
|
if (property.name() == wordAtCursor
|
||||||
&& !property.valueTypeName().isEmpty()) {
|
&& !property.valueTypeName().isEmpty()) {
|
||||||
query = doubleQuote + property.name() + QLatin1Char(':')
|
query = doubleQuote + property.name() + QLatin1Char(':')
|
||||||
@@ -239,7 +239,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
|
|||||||
+ QLatin1Char('+') + refToLook;
|
+ QLatin1Char('+') + refToLook;
|
||||||
} else {
|
} else {
|
||||||
// show properties
|
// show properties
|
||||||
foreach(QDeclarativeDebugPropertyReference property, ref.properties()) {
|
foreach (QDeclarativeDebugPropertyReference property, ref.properties()) {
|
||||||
if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) {
|
if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) {
|
||||||
query = doubleQuote + property.name() + QLatin1Char(':')
|
query = doubleQuote + property.name() + QLatin1Char(':')
|
||||||
+ doubleQuote + QLatin1Char('+') + property.name();
|
+ doubleQuote + QLatin1Char('+') + property.name();
|
||||||
@@ -250,7 +250,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!query.isEmpty()) {
|
if (!query.isEmpty()) {
|
||||||
m_debugQuery = m_clientProxy->queryExpressionResult(ref.debugId(),query);
|
m_debugQuery = m_clientProxy->queryExpressionResult(ref.debugId(),query, this);
|
||||||
connect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
|
connect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
|
||||||
this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
|
this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
|
||||||
}
|
}
|
||||||
@@ -281,13 +281,23 @@ void InspectorUi::connected(ClientProxy *clientProxy)
|
|||||||
{
|
{
|
||||||
m_clientProxy = clientProxy;
|
m_clientProxy = clientProxy;
|
||||||
|
|
||||||
|
QmlJS::Snapshot snapshot = modelManager()->snapshot();
|
||||||
|
for (QHash<QString, QmlJSLiveTextPreview *>::const_iterator it = m_textPreviews.constBegin();
|
||||||
|
it != m_textPreviews.constEnd(); ++it) {
|
||||||
|
Document::Ptr doc = snapshot.document(it.key());
|
||||||
|
it.value()->resetInitialDoc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||||
SLOT(gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>)));
|
SLOT(selectItems(QList<QDeclarativeDebugObjectReference>)));
|
||||||
|
|
||||||
connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList()));
|
connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList()));
|
||||||
connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
|
connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
|
||||||
connect(m_clientProxy, SIGNAL(contextPathUpdated(QStringList)),
|
connect(m_clientProxy, SIGNAL(propertyChanged(int, QByteArray,QVariant)),
|
||||||
m_crumblePath, SLOT(updateContextPath(QStringList)));
|
m_propertyInspector, SLOT(propertyValueChanged(int, QByteArray,QVariant)));
|
||||||
|
connect(m_propertyInspector, SIGNAL(changePropertyValue(int,QString,QString)),
|
||||||
|
this, SLOT(changePropertyValue(int,QString,QString)));
|
||||||
|
connect(m_clientProxy,SIGNAL(objectTreeUpdated()),this,SLOT(objectTreeReady()));
|
||||||
|
|
||||||
m_debugProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
|
m_debugProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
|
||||||
if (m_debugProject->activeTarget()
|
if (m_debugProject->activeTarget()
|
||||||
@@ -307,22 +317,34 @@ void InspectorUi::connected(ClientProxy *clientProxy)
|
|||||||
initializeDocuments();
|
initializeDocuments();
|
||||||
|
|
||||||
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
||||||
while(iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
iter.next();
|
iter.next();
|
||||||
iter.value()->setClientProxy(m_clientProxy);
|
iter.value()->setClientProxy(m_clientProxy);
|
||||||
iter.value()->updateDebugIds();
|
iter.value()->updateDebugIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectorUi::objectTreeReady()
|
||||||
|
{
|
||||||
|
// Should only run once, after debugger startup
|
||||||
|
if (!m_clientProxy->rootObjectReference().isEmpty()) {
|
||||||
|
selectItems(m_clientProxy->rootObjectReference());
|
||||||
|
disconnect(m_clientProxy,SIGNAL(objectTreeUpdated()),this,SLOT(objectTreeReady()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::disconnected()
|
void InspectorUi::disconnected()
|
||||||
{
|
{
|
||||||
disconnect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
disconnect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
|
||||||
this, SLOT(gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>)));
|
this, SLOT(selectItems(QList<QDeclarativeDebugObjectReference>)));
|
||||||
|
|
||||||
disconnect(m_clientProxy, SIGNAL(enginesChanged()), this, SLOT(updateEngineList()));
|
disconnect(m_clientProxy, SIGNAL(enginesChanged()), this, SLOT(updateEngineList()));
|
||||||
disconnect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
|
disconnect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded()));
|
||||||
disconnect(m_clientProxy, SIGNAL(contextPathUpdated(QStringList)),
|
disconnect(m_clientProxy, SIGNAL(propertyChanged(int, QByteArray,QVariant)),
|
||||||
m_crumblePath, SLOT(updateContextPath(QStringList)));
|
m_propertyInspector, SLOT(propertyValueChanged(int, QByteArray,QVariant)));
|
||||||
|
disconnect(m_propertyInspector, SIGNAL(changePropertyValue(int,QString,QString)),
|
||||||
|
this, SLOT(changePropertyValue(int,QString,QString)));
|
||||||
|
|
||||||
m_debugProject = 0;
|
m_debugProject = 0;
|
||||||
m_qmlEngine = 0;
|
m_qmlEngine = 0;
|
||||||
@@ -332,12 +354,12 @@ void InspectorUi::disconnected()
|
|||||||
applyChangesToQmlObserverHelper(false);
|
applyChangesToQmlObserverHelper(false);
|
||||||
|
|
||||||
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
||||||
while(iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
iter.next();
|
iter.next();
|
||||||
iter.value()->setClientProxy(0);
|
iter.value()->setClientProxy(0);
|
||||||
}
|
}
|
||||||
m_clientProxy = 0;
|
m_clientProxy = 0;
|
||||||
m_objectTreeWidget->clear();
|
m_propertyInspector->clear();
|
||||||
m_pendingPreviewDocumentNames.clear();
|
m_pendingPreviewDocumentNames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,19 +379,20 @@ void InspectorUi::updateEngineList()
|
|||||||
|
|
||||||
void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects)
|
void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects)
|
||||||
{
|
{
|
||||||
if (m_lastSelectedDebugId >= 0) {
|
if (m_selectionCallbackExpected) {
|
||||||
foreach (const QDeclarativeDebugObjectReference &ref, objects) {
|
m_selectionCallbackExpected = false;
|
||||||
if (ref.debugId() == m_lastSelectedDebugId) {
|
return;
|
||||||
// this is only the 'call back' after we have programatically set a new cursor
|
|
||||||
// position in
|
|
||||||
m_lastSelectedDebugId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_lastSelectedDebugId = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clientProxy->setSelectedItemsByObjectId(objects);
|
// QmlJSLiveTextPreview doesn't provide valid references, only correct debugIds. We need to remap them
|
||||||
|
QList <QDeclarativeDebugObjectReference> realList;
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &obj, objects) {
|
||||||
|
QDeclarativeDebugObjectReference clientRef = m_clientProxy->objectReferenceForId(obj.debugId());
|
||||||
|
realList << clientRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_clientProxy->setSelectedItemsByObjectId(realList);
|
||||||
|
selectItems(realList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::initializeDocuments()
|
void InspectorUi::initializeDocuments()
|
||||||
@@ -474,7 +497,8 @@ void InspectorUi::currentDebugProjectRemoved()
|
|||||||
|
|
||||||
void InspectorUi::resetViews()
|
void InspectorUi::resetViews()
|
||||||
{
|
{
|
||||||
m_crumblePath->updateContextPath(QStringList());
|
m_propertyInspector->clear();
|
||||||
|
m_crumblePath->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::reloadQmlViewer()
|
void InspectorUi::reloadQmlViewer()
|
||||||
@@ -483,31 +507,170 @@ void InspectorUi::reloadQmlViewer()
|
|||||||
m_clientProxy->reloadQmlViewer();
|
m_clientProxy->reloadQmlViewer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference>
|
inline QDeclarativeDebugObjectReference findParentRecursive( int goalDebugId,
|
||||||
objectReferences)
|
const QList< QDeclarativeDebugObjectReference > &objectsToSearch)
|
||||||
{
|
{
|
||||||
if (objectReferences.length())
|
if (goalDebugId == -1)
|
||||||
gotoObjectReferenceDefinition(objectReferences.first());
|
return QDeclarativeDebugObjectReference();
|
||||||
|
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &possibleParent, objectsToSearch) {
|
||||||
|
// Am I a root object? No parent
|
||||||
|
if ( possibleParent.debugId() == goalDebugId )
|
||||||
|
return QDeclarativeDebugObjectReference();
|
||||||
|
|
||||||
|
// Is the goal one of my children?
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &child, possibleParent.children())
|
||||||
|
if ( child.debugId() == goalDebugId )
|
||||||
|
return possibleParent;
|
||||||
|
|
||||||
|
// no luck? pass this on
|
||||||
|
QDeclarativeDebugObjectReference candidate = findParentRecursive(goalDebugId, possibleParent.children());
|
||||||
|
if (candidate.debugId() != -1)
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QDeclarativeDebugObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectorUi::selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences)
|
||||||
|
{
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &objref, objectReferences)
|
||||||
|
if (objref.debugId() != -1) {
|
||||||
|
// select only the first valid element of the list
|
||||||
|
|
||||||
|
m_clientProxy->removeAllObjectWatches();
|
||||||
|
m_clientProxy->addObjectWatch(objref.debugId());
|
||||||
|
QList <QDeclarativeDebugObjectReference> selectionList;
|
||||||
|
selectionList << objref;
|
||||||
|
m_propertyInspector->setCurrentObjects(selectionList);
|
||||||
|
populateCrumblePath(objref);
|
||||||
|
gotoObjectReferenceDefinition(objref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty list
|
||||||
|
m_propertyInspector->clear();
|
||||||
|
m_crumblePath->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString displayName(const QDeclarativeDebugObjectReference &obj)
|
||||||
|
{
|
||||||
|
// special! state names
|
||||||
|
if (obj.className() == "State") {
|
||||||
|
foreach (const QDeclarativeDebugPropertyReference &prop, obj.properties()) {
|
||||||
|
if (prop.name() == "name")
|
||||||
|
return prop.value().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// has id?
|
||||||
|
if (!obj.idString().isEmpty())
|
||||||
|
return obj.idString();
|
||||||
|
|
||||||
|
// return the simplified class name then
|
||||||
|
QString objTypeName = obj.className();
|
||||||
|
QString declarativeString("QDeclarative");
|
||||||
|
if (objTypeName.startsWith(declarativeString)) {
|
||||||
|
objTypeName = objTypeName.mid(declarativeString.length()).section('_',0,0);
|
||||||
|
}
|
||||||
|
return QString("<%1>").arg(objTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InspectorUi::isRoot(const QDeclarativeDebugObjectReference &obj) const
|
||||||
|
{
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &rootObj, m_clientProxy->rootObjectReference())
|
||||||
|
if (obj.debugId() == rootObj.debugId())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectorUi::populateCrumblePath(const QDeclarativeDebugObjectReference &objRef)
|
||||||
|
{
|
||||||
|
QStringList crumbleStrings;
|
||||||
|
QList <int> crumbleData;
|
||||||
|
|
||||||
|
// first find path by climbing the hierarchy
|
||||||
|
QDeclarativeDebugObjectReference ref = objRef;
|
||||||
|
crumbleData << objRef.debugId();
|
||||||
|
crumbleStrings << displayName(objRef);
|
||||||
|
|
||||||
|
while ((!isRoot(ref)) && (ref.debugId()!=-1)) {
|
||||||
|
ref = findParentRecursive(ref.debugId(), m_clientProxy->rootObjectReference());
|
||||||
|
crumbleData.push_front( ref.debugId() );
|
||||||
|
crumbleStrings.push_front( displayName(ref) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int itemIndex = crumbleData.length()-1;
|
||||||
|
|
||||||
|
// now append the children
|
||||||
|
foreach (const QDeclarativeDebugObjectReference &child, objRef.children()) {
|
||||||
|
crumbleData.push_back(child.debugId());
|
||||||
|
crumbleStrings.push_back( displayName(child) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_crumblePath->updateContextPath(crumbleStrings, crumbleData);
|
||||||
|
m_crumblePath->selectIndex(itemIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectorUi::selectItems(const QList<int> &objectIds)
|
||||||
|
{
|
||||||
|
QList<QDeclarativeDebugObjectReference> objectReferences;
|
||||||
|
foreach (int objectId, objectIds)
|
||||||
|
{
|
||||||
|
QDeclarativeDebugObjectReference ref = m_clientProxy->objectReferenceForId(objectId);
|
||||||
|
if (ref.debugId() == objectId)
|
||||||
|
objectReferences.append(ref);
|
||||||
|
}
|
||||||
|
if (objectReferences.length() > 0)
|
||||||
|
selectItems(objectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectorUi::changePropertyValue(int debugId,const QString &propertyName, const QString &valueExpression)
|
||||||
|
{
|
||||||
|
QString query = propertyName + '=' + valueExpression;
|
||||||
|
m_clientProxy->queryExpressionResult(debugId,query, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::enable()
|
void InspectorUi::enable()
|
||||||
{
|
{
|
||||||
m_toolbar->enable();
|
m_toolbar->enable();
|
||||||
m_crumblePath->setEnabled(true);
|
m_crumblePath->setEnabled(true);
|
||||||
m_objectTreeWidget->setEnabled(true);
|
m_propertyInspector->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::disable()
|
void InspectorUi::disable()
|
||||||
{
|
{
|
||||||
m_toolbar->disable();
|
m_toolbar->disable();
|
||||||
m_crumblePath->setEnabled(false);
|
m_crumblePath->setEnabled(false);
|
||||||
m_objectTreeWidget->setEnabled(false);
|
m_propertyInspector->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDeclarativeDebugObjectReference InspectorUi::objectReferenceForLocation(const QString &fileName, int cursorPosition) const
|
||||||
|
{
|
||||||
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
|
Core::IEditor *editor = editorManager->openEditor(fileName);
|
||||||
|
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
|
||||||
|
|
||||||
|
if (textEditor && m_clientProxy && textEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
|
||||||
|
if (cursorPosition == -1)
|
||||||
|
cursorPosition = textEditor->position();
|
||||||
|
QmlJSEditor::QmlJSTextEditor *qmlEditor =
|
||||||
|
static_cast<QmlJSEditor::QmlJSTextEditor*>(textEditor->widget());
|
||||||
|
|
||||||
|
if (QmlJS::AST::Node *node
|
||||||
|
= qmlEditor->semanticInfo().declaringMemberNoProperties(cursorPosition)) {
|
||||||
|
if (QmlJS::AST::UiObjectMember *objMember = node->uiObjectMemberCast()) {
|
||||||
|
return m_clientProxy->objectReferenceForLocation(
|
||||||
|
objMember->firstSourceLocation().startLine,
|
||||||
|
objMember->firstSourceLocation().startColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QDeclarativeDebugObjectReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj)
|
void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj)
|
||||||
{
|
{
|
||||||
Q_UNUSED(obj);
|
|
||||||
|
|
||||||
QDeclarativeDebugFileReference source = obj.source();
|
QDeclarativeDebugFileReference source = obj.source();
|
||||||
QString fileName = source.url().toLocalFile();
|
QString fileName = source.url().toLocalFile();
|
||||||
|
|
||||||
@@ -521,11 +684,14 @@ void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRef
|
|||||||
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
|
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
|
||||||
|
|
||||||
if (textEditor) {
|
if (textEditor) {
|
||||||
m_lastSelectedDebugId = obj.debugId();
|
QDeclarativeDebugObjectReference ref = objectReferenceForLocation(fileName);
|
||||||
|
if (ref.debugId() != obj.debugId())
|
||||||
editorManager->addCurrentPositionToNavigationHistory();
|
{
|
||||||
textEditor->gotoLine(source.lineNumber());
|
m_selectionCallbackExpected = true;
|
||||||
textEditor->widget()->setFocus();
|
editorManager->addCurrentPositionToNavigationHistory();
|
||||||
|
textEditor->gotoLine(source.lineNumber());
|
||||||
|
textEditor->widget()->setFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +719,7 @@ void InspectorUi::setupDockWidgets()
|
|||||||
m_crumblePath->setWindowTitle(tr("Context Path"));
|
m_crumblePath->setWindowTitle(tr("Context Path"));
|
||||||
connect(m_crumblePath, SIGNAL(elementClicked(int)), SLOT(crumblePathElementClicked(int)));
|
connect(m_crumblePath, SIGNAL(elementClicked(int)), SLOT(crumblePathElementClicked(int)));
|
||||||
|
|
||||||
m_objectTreeWidget = new QmlJSObjectTree;
|
m_propertyInspector = new QmlJSPropertyInspector;
|
||||||
|
|
||||||
QWidget *observerWidget = new QWidget;
|
QWidget *observerWidget = new QWidget;
|
||||||
observerWidget->setWindowTitle(tr("QML Observer"));
|
observerWidget->setWindowTitle(tr("QML Observer"));
|
||||||
@@ -564,7 +730,7 @@ void InspectorUi::setupDockWidgets()
|
|||||||
wlay->setSpacing(0);
|
wlay->setSpacing(0);
|
||||||
observerWidget->setLayout(wlay);
|
observerWidget->setLayout(wlay);
|
||||||
wlay->addWidget(m_toolbar->widget());
|
wlay->addWidget(m_toolbar->widget());
|
||||||
wlay->addWidget(m_objectTreeWidget);
|
wlay->addWidget(m_propertyInspector);
|
||||||
wlay->addWidget(m_crumblePath);
|
wlay->addWidget(m_crumblePath);
|
||||||
|
|
||||||
Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow();
|
Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow();
|
||||||
@@ -575,9 +741,9 @@ void InspectorUi::setupDockWidgets()
|
|||||||
|
|
||||||
void InspectorUi::crumblePathElementClicked(int pathIndex)
|
void InspectorUi::crumblePathElementClicked(int pathIndex)
|
||||||
{
|
{
|
||||||
if (m_clientProxy && m_clientProxy->isConnected() && !m_crumblePath->isEmpty()) {
|
QList <int> l;
|
||||||
m_clientProxy->setContextPathIndex(pathIndex);
|
l << m_crumblePath->debugIdForIndex(pathIndex);
|
||||||
}
|
selectItems(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InspectorUi::showExperimentalWarning()
|
bool InspectorUi::showExperimentalWarning()
|
||||||
@@ -623,7 +789,7 @@ void InspectorUi::setApplyChangesToQmlObserver(bool applyChanges)
|
|||||||
void InspectorUi::applyChangesToQmlObserverHelper(bool applyChanges)
|
void InspectorUi::applyChangesToQmlObserverHelper(bool applyChanges)
|
||||||
{
|
{
|
||||||
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews);
|
||||||
while(iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
iter.next();
|
iter.next();
|
||||||
iter.value()->setApplyChangesToQmlObserver(applyChanges);
|
iter.value()->setApplyChangesToQmlObserver(applyChanges);
|
||||||
}
|
}
|
||||||
@@ -648,7 +814,7 @@ void InspectorUi::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc)
|
|||||||
QmlJSLiveTextPreview *preview = createPreviewForEditor(editors.first());
|
QmlJSLiveTextPreview *preview = createPreviewForEditor(editors.first());
|
||||||
editors.removeFirst();
|
editors.removeFirst();
|
||||||
|
|
||||||
foreach(Core::IEditor *editor, editors) {
|
foreach (Core::IEditor *editor, editors) {
|
||||||
preview->associateEditor(editor);
|
preview->associateEditor(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -682,7 +848,8 @@ void InspectorUi::setupToolbar(bool doConnect)
|
|||||||
this, SLOT(setApplyChangesToQmlObserver(bool)));
|
this, SLOT(setApplyChangesToQmlObserver(bool)));
|
||||||
connect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
|
connect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
|
||||||
m_clientProxy, SLOT(showAppOnTop(bool)));
|
m_clientProxy, SLOT(showAppOnTop(bool)));
|
||||||
|
connect(m_toolbar, SIGNAL(filterTextChanged(QString)),
|
||||||
|
m_propertyInspector,SLOT(filterBy(QString)));
|
||||||
connect(m_clientProxy, SIGNAL(colorPickerActivated()),
|
connect(m_clientProxy, SIGNAL(colorPickerActivated()),
|
||||||
m_toolbar, SLOT(activateColorPicker()));
|
m_toolbar, SLOT(activateColorPicker()));
|
||||||
connect(m_clientProxy, SIGNAL(selectToolActivated()),
|
connect(m_clientProxy, SIGNAL(selectToolActivated()),
|
||||||
@@ -720,7 +887,8 @@ void InspectorUi::setupToolbar(bool doConnect)
|
|||||||
this, SLOT(setApplyChangesToQmlObserver(bool)));
|
this, SLOT(setApplyChangesToQmlObserver(bool)));
|
||||||
disconnect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
|
disconnect(m_toolbar, SIGNAL(showAppOnTopSelected(bool)),
|
||||||
m_clientProxy, SLOT(showAppOnTop(bool)));
|
m_clientProxy, SLOT(showAppOnTop(bool)));
|
||||||
|
disconnect(m_toolbar, SIGNAL(filterTextChanged(QString)),
|
||||||
|
m_propertyInspector,SLOT(filterBy(QString)));
|
||||||
disconnect(m_clientProxy, SIGNAL(colorPickerActivated()),
|
disconnect(m_clientProxy, SIGNAL(colorPickerActivated()),
|
||||||
m_toolbar, SLOT(activateColorPicker()));
|
m_toolbar, SLOT(activateColorPicker()));
|
||||||
disconnect(m_clientProxy, SIGNAL(selectToolActivated()),
|
disconnect(m_clientProxy, SIGNAL(selectToolActivated()),
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace QmlJSInspector {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlInspectorToolbar;
|
class QmlInspectorToolbar;
|
||||||
class QmlJSObjectTree;
|
class QmlJSPropertyInspector;
|
||||||
class ClientProxy;
|
class ClientProxy;
|
||||||
class InspectorSettings;
|
class InspectorSettings;
|
||||||
class ContextCrumblePath;
|
class ContextCrumblePath;
|
||||||
@@ -120,8 +120,11 @@ private slots:
|
|||||||
void enable();
|
void enable();
|
||||||
void disable();
|
void disable();
|
||||||
void gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj);
|
void gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj);
|
||||||
void gotoObjectReferenceDefinition(QList<QDeclarativeDebugObjectReference> objectReferences);
|
void selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences);
|
||||||
|
void selectItems(const QList<int> &objectIds);
|
||||||
void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects);
|
void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects);
|
||||||
|
void changePropertyValue(int debugId,const QString &propertyName, const QString &valueExpression);
|
||||||
|
void objectTreeReady();
|
||||||
|
|
||||||
void updateEngineList();
|
void updateEngineList();
|
||||||
|
|
||||||
@@ -146,19 +149,20 @@ private:
|
|||||||
void setupToolbar(bool doConnect);
|
void setupToolbar(bool doConnect);
|
||||||
void setupDockWidgets();
|
void setupDockWidgets();
|
||||||
QString filenameForShadowBuildFile(const QString &filename) const;
|
QString filenameForShadowBuildFile(const QString &filename) const;
|
||||||
|
void populateCrumblePath(const QDeclarativeDebugObjectReference &objRef);
|
||||||
|
bool isRoot(const QDeclarativeDebugObjectReference &obj) const;
|
||||||
|
QDeclarativeDebugObjectReference objectReferenceForLocation(const QString &fileName, int cursorPosition=-1) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_listeningToEditorManager;
|
bool m_listeningToEditorManager;
|
||||||
|
|
||||||
QmlInspectorToolbar *m_toolbar;
|
QmlInspectorToolbar *m_toolbar;
|
||||||
ContextCrumblePath *m_crumblePath;
|
ContextCrumblePath *m_crumblePath;
|
||||||
QmlJSObjectTree *m_objectTreeWidget;
|
QmlJSPropertyInspector *m_propertyInspector;
|
||||||
|
|
||||||
InspectorSettings *m_settings;
|
InspectorSettings *m_settings;
|
||||||
ClientProxy *m_clientProxy;
|
ClientProxy *m_clientProxy;
|
||||||
QObject *m_qmlEngine;
|
QObject *m_qmlEngine;
|
||||||
QDeclarativeDebugExpressionQuery *m_debugQuery;
|
QDeclarativeDebugExpressionQuery *m_debugQuery;
|
||||||
int m_lastSelectedDebugId;
|
|
||||||
|
|
||||||
// Qml/JS integration
|
// Qml/JS integration
|
||||||
QHash<QString, QmlJSLiveTextPreview *> m_textPreviews;
|
QHash<QString, QmlJSLiveTextPreview *> m_textPreviews;
|
||||||
@@ -172,6 +176,7 @@ private:
|
|||||||
Utils::FileInProjectFinder m_projectFinder;
|
Utils::FileInProjectFinder m_projectFinder;
|
||||||
|
|
||||||
static InspectorUi *m_instance;
|
static InspectorUi *m_instance;
|
||||||
|
bool m_selectionCallbackExpected;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ qmljstoolbarcolorbox.h \
|
|||||||
qmljsobserverclient.h \
|
qmljsobserverclient.h \
|
||||||
qmljscontextcrumblepath.h \
|
qmljscontextcrumblepath.h \
|
||||||
qmljsinspectorsettings.h \
|
qmljsinspectorsettings.h \
|
||||||
qmljsobjecttree.h
|
qmljspropertyinspector.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
qmljsinspectorplugin.cpp \
|
qmljsinspectorplugin.cpp \
|
||||||
@@ -31,7 +31,7 @@ qmljstoolbarcolorbox.cpp \
|
|||||||
qmljsobserverclient.cpp \
|
qmljsobserverclient.cpp \
|
||||||
qmljscontextcrumblepath.cpp \
|
qmljscontextcrumblepath.cpp \
|
||||||
qmljsinspectorsettings.cpp \
|
qmljsinspectorsettings.cpp \
|
||||||
qmljsobjecttree.cpp
|
qmljspropertyinspector.cpp
|
||||||
|
|
||||||
include(../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
|
include(../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
|
||||||
|
|
||||||
|
|||||||
@@ -1,242 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
** No Commercial Usage
|
|
||||||
**
|
|
||||||
** This file contains pre-release code and may not be distributed.
|
|
||||||
** You may use this file in accordance with the terms and conditions
|
|
||||||
** contained in the Technology Preview License Agreement accompanying
|
|
||||||
** this package.
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 2.1 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
||||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#include "qmljsobjecttree.h"
|
|
||||||
|
|
||||||
#include <QContextMenuEvent>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QtGui/QMenu>
|
|
||||||
#include <QtGui/QAction>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QInputDialog>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// ObjectTreeItem
|
|
||||||
// *************************************************************************
|
|
||||||
|
|
||||||
class ObjectTreeItem : public QTreeWidgetItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit ObjectTreeItem(QTreeWidget *widget, int type = 0);
|
|
||||||
ObjectTreeItem(QTreeWidgetItem *parentItem, int type = 0);
|
|
||||||
QVariant data (int column, int role) const;
|
|
||||||
void setData (int column, int role, const QVariant & value);
|
|
||||||
|
|
||||||
void setHasValidDebugId(bool value);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_hasValidDebugId;
|
|
||||||
};
|
|
||||||
|
|
||||||
ObjectTreeItem::ObjectTreeItem(QTreeWidget *widget, int type) :
|
|
||||||
QTreeWidgetItem(widget, type), m_hasValidDebugId(true)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectTreeItem::ObjectTreeItem(QTreeWidgetItem *parentItem, int type) :
|
|
||||||
QTreeWidgetItem(parentItem, type), m_hasValidDebugId(true)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ObjectTreeItem::data (int column, int role) const
|
|
||||||
{
|
|
||||||
if (role == Qt::ForegroundRole)
|
|
||||||
return m_hasValidDebugId ? qApp->palette().color(QPalette::Foreground) : qApp->palette().color(QPalette::Disabled, QPalette::Foreground);
|
|
||||||
|
|
||||||
return QTreeWidgetItem::data(column, role);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectTreeItem::setData (int column, int role, const QVariant & value)
|
|
||||||
{
|
|
||||||
QTreeWidgetItem::setData(column, role, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectTreeItem::setHasValidDebugId(bool value)
|
|
||||||
{
|
|
||||||
m_hasValidDebugId = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// QmlJSObjectTree
|
|
||||||
// *************************************************************************
|
|
||||||
|
|
||||||
QmlJSObjectTree::QmlJSObjectTree(QWidget *parent)
|
|
||||||
: QTreeWidget(parent)
|
|
||||||
, m_clickedItem(0)
|
|
||||||
, m_currentObjectDebugId(0)
|
|
||||||
{
|
|
||||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
|
||||||
setFrameStyle(QFrame::NoFrame);
|
|
||||||
setHeaderHidden(true);
|
|
||||||
setExpandsOnDoubleClick(false);
|
|
||||||
|
|
||||||
m_goToFileAction = new QAction(tr("Go to file"), this);
|
|
||||||
connect(m_goToFileAction, SIGNAL(triggered()), SLOT(goToFile()));
|
|
||||||
|
|
||||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
|
|
||||||
SLOT(currentItemChanged(QTreeWidgetItem *)));
|
|
||||||
connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
|
|
||||||
SLOT(activated(QTreeWidgetItem *)));
|
|
||||||
connect(this, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::selectionChanged()
|
|
||||||
{
|
|
||||||
if (selectedItems().isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::setCurrentObject(int debugId)
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *item = findItemByObjectId(debugId);
|
|
||||||
if (item) {
|
|
||||||
setCurrentItem(item);
|
|
||||||
scrollToItem(item);
|
|
||||||
item->setExpanded(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::currentItemChanged(QTreeWidgetItem *item)
|
|
||||||
{
|
|
||||||
if (!item)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
|
|
||||||
if (obj.debugId() >= 0)
|
|
||||||
emit currentObjectChanged(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::activated(QTreeWidgetItem *item)
|
|
||||||
{
|
|
||||||
if (!item)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
|
|
||||||
if (obj.debugId() >= 0)
|
|
||||||
emit activated(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::buildTree(const QDeclarativeDebugObjectReference &obj, QTreeWidgetItem *parent)
|
|
||||||
{
|
|
||||||
if (!parent)
|
|
||||||
clear();
|
|
||||||
|
|
||||||
if (obj.contextDebugId() < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ObjectTreeItem *item = parent ? new ObjectTreeItem(parent) : new ObjectTreeItem(this);
|
|
||||||
if (obj.idString().isEmpty())
|
|
||||||
item->setText(0, QString("<%1>").arg(obj.className()));
|
|
||||||
else
|
|
||||||
item->setText(0, obj.idString());
|
|
||||||
item->setData(0, Qt::UserRole, qVariantFromValue(obj));
|
|
||||||
|
|
||||||
if (parent && obj.contextDebugId() >= 0
|
|
||||||
&& obj.contextDebugId() != parent->data(0, Qt::UserRole
|
|
||||||
).value<QDeclarativeDebugObjectReference>().contextDebugId())
|
|
||||||
{
|
|
||||||
|
|
||||||
QDeclarativeDebugFileReference source = obj.source();
|
|
||||||
if (!source.url().isEmpty()) {
|
|
||||||
QString toolTipString = tr("Url: ") + source.url().toString();
|
|
||||||
item->setToolTip(0, toolTipString);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item->setExpanded(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj.contextDebugId() < 0)
|
|
||||||
item->setHasValidDebugId(false);
|
|
||||||
|
|
||||||
for (int ii = 0; ii < obj.children().count(); ++ii)
|
|
||||||
buildTree(obj.children().at(ii), item);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem *QmlJSObjectTree::findItemByObjectId(int debugId) const
|
|
||||||
{
|
|
||||||
for (int i=0; i<topLevelItemCount(); ++i) {
|
|
||||||
QTreeWidgetItem *item = findItem(topLevelItem(i), debugId);
|
|
||||||
if (item)
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem *QmlJSObjectTree::findItem(QTreeWidgetItem *item, int debugId) const
|
|
||||||
{
|
|
||||||
if (item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>().debugId() == debugId)
|
|
||||||
return item;
|
|
||||||
|
|
||||||
QTreeWidgetItem *child;
|
|
||||||
for (int i=0; i<item->childCount(); ++i) {
|
|
||||||
child = findItem(item->child(i), debugId);
|
|
||||||
if (child)
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::goToFile()
|
|
||||||
{
|
|
||||||
QDeclarativeDebugObjectReference obj =
|
|
||||||
currentItem()->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
|
|
||||||
|
|
||||||
if (obj.debugId() >= 0)
|
|
||||||
emit activated(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSObjectTree::contextMenuEvent(QContextMenuEvent *event)
|
|
||||||
{
|
|
||||||
m_clickedItem = itemAt(QPoint(event->pos().x(),
|
|
||||||
event->pos().y() ));
|
|
||||||
if (!m_clickedItem)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QMenu menu;
|
|
||||||
menu.addAction(m_goToFileAction);
|
|
||||||
menu.exec(event->globalPos());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // QmlJSInspector
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
**
|
|
||||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
||||||
**
|
|
||||||
** No Commercial Usage
|
|
||||||
**
|
|
||||||
** This file contains pre-release code and may not be distributed.
|
|
||||||
** You may use this file in accordance with the terms and conditions
|
|
||||||
** contained in the Technology Preview License Agreement accompanying
|
|
||||||
** this package.
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
**
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 2.1 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
||||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** If you have questions regarding the use of this file, please contact
|
|
||||||
** Nokia at qt-info@nokia.com.
|
|
||||||
**
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef OBJECTTREE_H
|
|
||||||
#define OBJECTTREE_H
|
|
||||||
|
|
||||||
#include <qmljsprivateapi.h>
|
|
||||||
#include <QtGui/QTreeWidget>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class QTreeWidgetItem;
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace QmlJSInspector {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class QmlJSObjectTree : public QTreeWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QmlJSObjectTree(QWidget *parent = 0);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void currentObjectChanged(const QDeclarativeDebugObjectReference &);
|
|
||||||
void activated(const QDeclarativeDebugObjectReference &);
|
|
||||||
void expressionWatchRequested(const QDeclarativeDebugObjectReference &, const QString &);
|
|
||||||
void contextHelpIdChanged(const QString &contextHelpId);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setCurrentObject(int debugId); // select an object in the tree
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void contextMenuEvent(QContextMenuEvent *);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void currentItemChanged(QTreeWidgetItem *);
|
|
||||||
void activated(QTreeWidgetItem *);
|
|
||||||
void selectionChanged();
|
|
||||||
void goToFile();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QTreeWidgetItem *findItemByObjectId(int debugId) const;
|
|
||||||
QTreeWidgetItem *findItem(QTreeWidgetItem *item, int debugId) const;
|
|
||||||
void buildTree(const QDeclarativeDebugObjectReference &, QTreeWidgetItem *parent);
|
|
||||||
|
|
||||||
QTreeWidgetItem *m_clickedItem;
|
|
||||||
QAction *m_addWatchAction;
|
|
||||||
QAction *m_goToFileAction;
|
|
||||||
int m_currentObjectDebugId;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // QmlJSInspector
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user