KHtml

localvariabledock.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 2006 Matt Broadstone ([email protected])
4  * (C) 2007 Maks Orlovich <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "localvariabledock.h"
22 
23 #include <QVBoxLayout>
24 #include <QTreeWidget>
25 #include <QEventLoop>
26 #include <QStringList>
27 
28 #include <kjs/interpreter.h>
29 #include <kjs/PropertyNameArray.h>
30 #include <kjs/context.h>
31 #include <kjs/scope_chain.h>
32 #include <kjs/JSVariableObject.h>
33 #include <kjs/object.h>
34 #include "khtml_debug.h"
35 #include <klocalizedstring.h>
36 
37 #include "value2string.h"
38 
39 namespace KJSDebugger
40 {
41 
42 LocalVariablesDock::LocalVariablesDock(QWidget *parent)
43  : QDockWidget(i18n("Local Variables"), parent), m_execState(0)
44 {
45  setFeatures(DockWidgetMovable | DockWidgetFloatable);
46  m_view = new QTreeWidget(this);
47 
48  m_view->setColumnCount(2);
49 
50  QStringList headers;
51  headers << i18n("Reference");
52  headers << i18n("Value");
53  m_view->setHeaderLabels(headers);
54 
55  connect(m_view, SIGNAL(itemExpanded(QTreeWidgetItem*)),
56  this, SLOT(slotItemExpanded(QTreeWidgetItem*)));
57 
58  setWidget(m_view);
59 }
60 
61 LocalVariablesDock::~LocalVariablesDock()
62 {
63 }
64 
65 void LocalVariablesDock::updateValue(KJS::ExecState *exec, KJS::JSValue *val,
66  QTreeWidgetItem *item, bool recurse)
67 {
68  // Note: parent is responsible for setting our name..
69  item->setText(1, valueToString(val));
70  if (recurse) {
71  if (val->isObject()) {
72  updateObjectProperties(exec, val, item);
73  } else {
74  // It has no kids, so treeview item better not, either
76  qDeleteAll(kids);
77  }
78  }
79 }
80 
81 void LocalVariablesDock::updateObjectProperties(KJS::ExecState *exec, KJS::JSValue *val,
82  QTreeWidgetItem *item, bool globalObject)
83 {
84  bool root = (item == m_view->invisibleRootItem());
85 
86  // We have to be careful here -- we don't want to recurse if we're not open;
87  // except for root since we may want the + there
88  bool recurse = item->isExpanded() || root;
89 
90  QStringList props;
91  KJS::JSObject *obj = 0;
92 
93  // Get the list of all relevant properties..
94  // Note: val may be null for root case..
95  if (val) {
96  assert(val->isObject());
97 
98  obj = val->getObject();
99  KJS::PropertyNameArray jsProps;
100 
101  // We use getOwnPropertyNames and not getPropertyNames here
102  // to not include things from the prototype
103  obj->getOwnPropertyNames(exec, jsProps, KJS::PropertyMap::ExcludeDontEnumProperties);
104 
105  for (int pos = 0; pos < jsProps.size(); ++pos) {
106  // For global (window) objects, we only show hash table properties,
107  // for less cluttered display.
108  if (globalObject && !obj->getDirect(jsProps[pos])) {
109  continue;
110  }
111 
112  props.append(jsProps[pos].ustring().qstring());
113  }
114  }
115 
116  // If we're not an activation, also list the prototype, as __proto__
117  if (val && !val->getObject()->isActivation()) {
118  props << QLatin1String("__proto__");
119  }
120 
121  // If we're the root, also pretend 'this' is there.
122  if (root && exec) {
123  props << QLatin1String("this");
124  }
125 
126  // Sort them, to make updates easier.
127  props.sort();
128 
129  // Do we need more or less nodes?
130  while (props.size() < item->childCount()) {
131  delete item->takeChild(item->childCount() - 1);
132  }
133 
134  while (props.size() > item->childCount()) {
135  item->addChild(new QTreeWidgetItem);
136  }
137 
138  // Update names and values.
139  for (int pos = 0; pos < props.size(); ++pos) {
140  QString propName = props[pos];
141  QTreeWidgetItem *kid = item->child(pos);
142  kid->setText(0, propName);
143 
144  if (root && propName == "this") {
145  updateValue(exec, exec->thisValue(), kid, true);
146  } else {
147  updateValue(exec, obj->get(exec, KJS::Identifier(KJS::UString(props[pos]))), kid, recurse);
148  }
149  }
150 }
151 
152 void LocalVariablesDock::slotItemExpanded(QTreeWidgetItem *item)
153 {
154  Q_UNUSED(item);
155  updateDisplay(m_execState);
156 }
157 
158 void LocalVariablesDock::updateDisplay(KJS::ExecState *exec)
159 {
160  m_execState = exec;
161 
162  // Find out out scope object...
163  KJS::JSObject *scopeObject = 0;
164  KJS::Context *context = 0;
165 
166  if (exec) {
167  context = exec->context();
168  }
169 
170  // Find the nearest local scope, or
171  // failing that the topmost scope
172  if (context) {
173  KJS::ScopeChain chain = context->scopeChain();
174  for (KJS::ScopeChainIterator iter = chain.begin();
175  iter != chain.end(); ++iter) {
176  scopeObject = *iter;
177  if (scopeObject->isActivation()) {
178  break;
179  }
180  }
181  }
182 
183  updateObjectProperties(exec, scopeObject, m_view->invisibleRootItem(),
184  scopeObject && !scopeObject->isActivation());
185 }
186 
187 }
QTreeWidgetItem * child(int index) const const
bool isExpanded() const const
int size() const const
JSObject * thisValue() const
void append(const T &value)
QList< QTreeWidgetItem * > takeChildren()
void addChild(QTreeWidgetItem *child)
QString i18n(const char *text, const TYPE &arg...)
void setText(int column, const QString &text)
const ScopeChain & scopeChain() const
void sort(Qt::CaseSensitivity cs)
int childCount() const const
QTreeWidgetItem * takeChild(int index)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:06 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.