00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#include "variablewidget.h"
00019
#include "jdbparser.h"
00020
00021
#include <kdebug.h>
00022
#include <kpopupmenu.h>
00023
#include <klineedit.h>
00024
00025
#include <qheader.h>
00026
#include <qlabel.h>
00027
#include <qlayout.h>
00028
#include <qpainter.h>
00029
#include <qpushbutton.h>
00030
#include <qregexp.h>
00031
#include <qcursor.h>
00032
#include <klocale.h>
00033
00034
#if defined(DBG_MONITOR)
00035
#define DBG_DISPLAY(X) {emit rawData(QString(X));}
00036
#else
00037 #define DBG_DISPLAY(X) {;}
00038
#endif
00039
00040
00041
00042
namespace JAVADebugger
00043 {
00044
00046 static JDBParser *
parser = 0;
00047
00048 static JDBParser *
getParser()
00049 {
00050
if (!
parser)
00051
parser =
new JDBParser;
00052
00053
return parser;
00054 }
00055
00056
00057
00058
00059
00060
00061 VariableWidget::VariableWidget(
QWidget *parent,
const char *name)
00062 :
QWidget(parent, name)
00063 {
00064
varTree_ =
new VariableTree(
this);
00065
QLabel *label =
new QLabel(i18n(
"Watch:"),
this);
00066
watchVarEntry_ =
new KLineEdit(
this);
00067
QPushButton *addButton =
new QPushButton(i18n(
"Add"),
this);
00068
00069
QBoxLayout *watchEntry =
new QHBoxLayout();
00070 watchEntry->
addWidget(
watchVarEntry_);
00071 watchEntry->
addWidget(label);
00072 watchEntry->
addWidget(addButton);
00073
00074
QVBoxLayout *topLayout =
new QVBoxLayout(
this, 2);
00075 topLayout->addWidget(
varTree_, 10);
00076 topLayout->addLayout(watchEntry);
00077
00078 connect( addButton, SIGNAL(clicked()), SLOT(
slotAddWatchVariable()) );
00079 connect(
watchVarEntry_, SIGNAL(returnPressed()), SLOT(
slotAddWatchVariable()) );
00080 }
00081
00082
00083
00084 void VariableWidget::clear()
00085 {
00086
varTree_->clear();
00087 }
00088
00089
00090
00091 void VariableWidget::slotAddWatchVariable()
00092 {
00093
QString watchVar(
watchVarEntry_->text());
00094
if (!watchVar.isEmpty())
00095
varTree_->
slotAddWatchVariable(watchVar);
00096 }
00097
00098
00099
00100
00101
00102 VariableTree::VariableTree(
VariableWidget *parent,
const char *name)
00103 :
KListView(parent, name),
00104 activeFlag_(0)
00105 {
00106 setRootIsDecorated(
true);
00107 setAllColumnsShowFocus(
true);
00108 setSorting(-1);
00109 addColumn(i18n(
"Variable"));
00110 addColumn(i18n(
"Value"));
00111
00112 header()->hide();
00113 setMultiSelection(
false);
00114
00115 connect(
this, SIGNAL(contextMenu(
KListView*,
QListViewItem*,
const QPoint&)),
00116 SLOT(
slotContextMenu(
KListView*,
QListViewItem*)) );
00117 }
00118
00119
00120
00121 VariableTree::~VariableTree()
00122 {
00123 }
00124
00125
00126
00127 void VariableTree::slotContextMenu(
KListView *,
QListViewItem *item)
00128 {
00129
if (!item)
00130
return;
00131
00132 setSelected(item,
true);
00133
00134
if (item->parent()) {
00135
KPopupMenu popup(item->text(VarNameCol),
this);
00136
int idRemoveWatch = -1;
00137
if (dynamic_cast<WatchRoot*>(
findRoot(item)))
00138 idRemoveWatch = popup.insertItem( i18n(
"Remove Watch Variable") );
00139
int idToggleWatch = popup.insertItem( i18n(
"Toggle Watchpoint") );
00140
00141
int res = popup.exec(QCursor::pos());
00142
00143
if (res == idRemoveWatch)
00144
delete item;
00145
else if (res == idToggleWatch) {
00146
if (
VarItem *item = dynamic_cast<VarItem*>(currentItem()))
00147 emit
toggleWatchpoint(item->
fullName());
00148 }
00149 }
00150 }
00151
00152
00153
00154 void VariableTree::slotAddWatchVariable(
const QString &watchVar)
00155 {
00156
kdDebug(9012) <<
"Add watch variable: " << watchVar <<
endl;
00157
VarItem *varItem =
new VarItem(
findWatch(), watchVar, typeUnknown);
00158 emit
expandItem(varItem);
00159 }
00160
00161
00162
00163 void VariableTree::setLocalViewState(
bool localsOn,
int frameNo)
00164 {
00165
00166
00167
if (!localsOn) {
00168
QListViewItem *sibling = firstChild();
00169
while (sibling) {
00170
FrameRoot *frame = dynamic_cast<FrameRoot*> (sibling);
00171
if (frame && frame->isOpen()) {
00172 localsOn =
true;
00173
break;
00174 }
00175
00176 sibling = sibling->nextSibling();
00177 }
00178 }
00179
00180 emit
setLocalViewState(localsOn);
00181 emit
selectFrame(frameNo);
00182 }
00183
00184
00185
00186
00187 QListViewItem *VariableTree::findRoot(
QListViewItem *item)
const
00188
{
00189
while (item->parent())
00190 item = item->parent();
00191
00192
return item;
00193 }
00194
00195
00196
00197 FrameRoot *VariableTree::findFrame(
int frameNo)
const
00198
{
00199
QListViewItem *sibling = firstChild();
00200
00201
00202
00203
while (sibling) {
00204
FrameRoot *frame = dynamic_cast<FrameRoot*> (sibling);
00205
if (frame && frame->
getFrameNo() == frameNo)
00206
return frame;
00207
00208 sibling = sibling->nextSibling();
00209 }
00210
00211
return 0;
00212 }
00213
00214
00215
00216 WatchRoot *VariableTree::findWatch()
00217 {
00218
QListViewItem *sibling = firstChild();
00219
00220
while (sibling) {
00221
if (
WatchRoot *watch = dynamic_cast<WatchRoot*> (sibling))
00222
return watch;
00223
00224 sibling = sibling->nextSibling();
00225 }
00226
00227
return new WatchRoot(
this);
00228 }
00229
00230
00231
00232 void VariableTree::trim()
00233 {
00234
QListViewItem *child = firstChild();
00235
00236
while (child) {
00237
QListViewItem *nextChild = child->nextSibling();
00238
00239
00240
if (!(dynamic_cast<WatchRoot*> (child))) {
00241
if (
TrimmableItem *item = dynamic_cast<TrimmableItem*> (child)) {
00242
if (item->
isActive())
00243 item->
trim();
00244
else
00245
delete item;
00246 }
00247 }
00248 child = nextChild;
00249 }
00250 }
00251
00252
00253
00254 void VariableTree::trimExcessFrames()
00255 {
00256
QListViewItem *child = firstChild();
00257
00258
while (child) {
00259
QListViewItem *nextChild = child->nextSibling();
00260
if (
FrameRoot *frame = dynamic_cast<FrameRoot*> (child)) {
00261
if (frame->
getFrameNo() != 0)
00262
delete frame;
00263 }
00264 child = nextChild;
00265 }
00266 }
00267
00268
00269
00270 QListViewItem *VariableTree::lastChild()
const
00271
{
00272
QListViewItem *child = firstChild();
00273
if (child)
00274
while (
QListViewItem *nextChild = child->nextSibling())
00275 child = nextChild;
00276
00277
return child;
00278 }
00279
00280
00281
00282
00283
00284 TrimmableItem::TrimmableItem(
VariableTree *parent)
00285 :
QListViewItem (parent, parent->lastChild()),
00286 activeFlag_(0)
00287 {
00288
setActive();
00289 }
00290
00291
00292
00293 TrimmableItem::TrimmableItem(
TrimmableItem *parent)
00294 :
QListViewItem (parent, parent->lastChild()),
00295 activeFlag_(0),
00296 waitingForData_(false)
00297 {
00298
setActive();
00299 }
00300
00301
00302
00303 TrimmableItem::~TrimmableItem()
00304 {
00305 }
00306
00307
00308
00309 int TrimmableItem::rootActiveFlag()
const
00310
{
00311
return ((
VariableTree*)listView())->activeFlag();
00312 }
00313
00314
00315
00316 bool TrimmableItem::isTrimmable()
const
00317
{
00318
return !
waitingForData_;
00319 }
00320
00321
00322
00323 QListViewItem *TrimmableItem::lastChild()
const
00324
{
00325
QListViewItem *child = firstChild();
00326
if (child)
00327
while (
QListViewItem *nextChild = child->nextSibling())
00328 child = nextChild;
00329
00330
return child;
00331 }
00332
00333
00334
00335 TrimmableItem *TrimmableItem::findMatch(
const QString &match, DataType type)
const
00336
{
00337
QListViewItem *child = firstChild();
00338
00339
00340
while (child) {
00341
if (child->text(VarNameCol) == match) {
00342
if (
TrimmableItem *item = dynamic_cast<TrimmableItem*> (child))
00343
if (item->
getDataType() == type)
00344
return item;
00345 }
00346
00347 child = child->nextSibling();
00348 }
00349
00350
return 0;
00351 }
00352
00353
00354
00355 void TrimmableItem::trim()
00356 {
00357
QListViewItem *child = firstChild();
00358
00359
while (child) {
00360
QListViewItem *nextChild = child->nextSibling();
00361
if (
TrimmableItem *item = dynamic_cast<TrimmableItem*>(child)) {
00362
00363
if (
isTrimmable()) {
00364
if (item->
isActive())
00365 item->
trim();
00366
else
00367
delete item;
00368 }
00369 }
00370 child = nextChild;
00371 }
00372 }
00373
00374
00375
00376 DataType TrimmableItem::getDataType()
const
00377
{
00378
return typeUnknown;
00379 }
00380
00381
00382
00383 void TrimmableItem::setCache(
const QCString&)
00384 {
00385 Q_ASSERT(
false);
00386 }
00387
00388
00389
00390 QCString TrimmableItem::getCache()
00391 {
00392 Q_ASSERT(
false);
00393
return QCString();
00394 }
00395
00396
00397
00398 void TrimmableItem::updateValue(
char* )
00399 {
00400
waitingForData_ =
false;
00401 }
00402
00403
00404
00405 QString TrimmableItem::key (
int,
bool)
const
00406
{
00407
return QString::null;
00408 }
00409
00410
00411
00412
00413
00414 VarItem::VarItem(
TrimmableItem *parent,
const QString &varName, DataType dataType)
00415 :
TrimmableItem (parent),
00416 cache_(
QCString()),
00417 dataType_(dataType),
00418 highlight_(false)
00419 {
00420
setText(VarNameCol, varName);
00421 }
00422
00423
00424
00425 VarItem::~VarItem()
00426 {
00427 }
00428
00429
00430
00431 QString VarItem::varPath()
const
00432
{
00433
QString vPath(
"");
00434
const VarItem *item =
this;
00435
00436
00437
while ((item = dynamic_cast<const VarItem*> (item->parent()))) {
00438
if (item->
getDataType() != typeArray) {
00439
if ((item->text(VarNameCol))[0] !=
'<') {
00440
QString itemName = item->text(VarNameCol);
00441
if (vPath.isEmpty())
00442 vPath = itemName.replace(
QRegExp(
"^static "),
"");
00443
else
00444 vPath = itemName.replace(
QRegExp(
"^static "),
"") +
"." + vPath;
00445 }
00446 }
00447 }
00448
00449
return vPath;
00450 }
00451
00452
00453
00454 QString VarItem::fullName()
const
00455
{
00456
QString itemName(
getName());
00457 Q_ASSERT (!itemName.isNull());
00458
QString vPath =
varPath();
00459
if (itemName[0] ==
'<')
00460
return vPath;
00461
00462
if (vPath.isEmpty())
00463
return itemName.replace(
QRegExp(
"^static "),
"");
00464
00465
return varPath() +
"." + itemName.replace(
QRegExp(
"^static "),
"");
00466 }
00467
00468
00469
00470 void VarItem::setText(
int column,
const QString &data)
00471 {
00472
if (!
isActive() && isOpen() &&
dataType_ == typePointer) {
00473
waitingForData();
00474 ((
VariableTree*)listView())->expandItem(
this);
00475 }
00476
00477
setActive();
00478
if (column == ValueCol) {
00479
QString oldValue(
text(column));
00480
if (!oldValue.isEmpty())
00481
highlight_ = (oldValue !=
QString(data));
00482 }
00483
00484 QListViewItem::setText(column, data);
00485 repaint();
00486 }
00487
00488
00489
00490 void VarItem::updateValue(
char *buf)
00491 {
00492 TrimmableItem::updateValue(buf);
00493
00494
00495
if ((strncmp(buf,
"There is no member named len.", 29) == 0) ||
00496 (strncmp(buf,
"There is no member or method named len.", 39) == 0))
00497
return;
00498
00499
if (*buf ==
'$') {
00500
if (
char *end = strchr(buf,
'='))
00501 buf = end+2;
00502 }
00503
00504
if (
dataType_ == typeUnknown) {
00505
dataType_ =
getParser()->
determineType(buf);
00506
if (
dataType_ == typeArray)
00507 buf++;
00508
00509
00510
00511
QString varName =
getName();
00512
if (
dataType_ == typePointer && varName[0] ==
'/')
00513
dataType_ = typeValue;
00514 }
00515
00516
getParser()->
parseData(
this, buf,
true,
false);
00517
setActive();
00518 }
00519
00520
00521
00522 void VarItem::setCache(
const QCString &value)
00523 {
00524
cache_ = value;
00525 setExpandable(
true);
00526
checkForRequests();
00527
if (isOpen())
00528
setOpen(
true);
00529
setActive();
00530 }
00531
00532
00533
00534 void VarItem::setOpen(
bool open)
00535 {
00536
if (open) {
00537
if (
cache_) {
00538
QCString value =
cache_;
00539 cache_ =
QCString();
00540
getParser()->
parseData(
this, value.data(),
false,
false);
00541
trim();
00542 }
else {
00543
if (
dataType_ == typePointer ||
dataType_ == typeReference) {
00544
waitingForData();
00545 emit ((
VariableTree*)listView())->expandItem(
this);
00546 }
00547 }
00548 }
00549
00550 QListViewItem::setOpen(open);
00551 }
00552
00553
00554
00555 QCString VarItem::getCache()
00556 {
00557
return cache_;
00558 }
00559
00560
00561
00562 void VarItem::checkForRequests()
00563 {
00565
00566
00567
if (strncmp(
cache_,
"<QArrayT<char>> = {<QGArray> = {shd = ", 38) == 0) {
00568
waitingForData();
00569 emit ((
VariableTree*)listView())->expandUserItem(
this,
00570
fullName().latin1()+
QCString(
".shd.data"));
00571 }
00572
00573
00574
if (strncmp(
cache_,
"dPath = {<QArrayT<char>> = {<QGArray> = {shd", 44) == 0) {
00575
waitingForData();
00576 emit ((
VariableTree*)listView())->expandUserItem(
this,
00577
fullName().latin1()+
QCString(
".dPath.shd.data"));
00578 }
00579
00580
00583
if (strncmp(
cache_,
"d = 0x", 6) == 0) {
00584
waitingForData();
00585 emit ((
VariableTree*)listView())->expandUserItem(
this,
00586
QCString().sprintf(
"(($len=($data=%s.d).len)?$data.unicode.rw@($len>100?200:$len*2):\"\")",
00587
fullName().latin1()));
00588 }
00589
00590
00591
if (strncmp(
cache_,
"<QArray<char>> = {<QGArray> = {shd = ", 37) == 0) {
00592
waitingForData();
00593 emit ((
VariableTree*)listView())->expandUserItem(
this,
00594
fullName().latin1()+
QCString(
".shd.data"));
00595 }
00596
00597
00598
if (strncmp(
cache_,
"dPath = {d = 0x", 15) == 0) {
00599
waitingForData();
00600 ((
VariableTree*)listView())->expandUserItem(
this,
00601
QCString().sprintf(
"(($len=($data=%s.dPath.d).len)?$data.unicode.rw@($len>100?200:$len*2):\"\")",
00602
fullName().latin1()));
00603 }
00604 }
00605
00606
00607
00608 DataType VarItem::getDataType()
const
00609
{
00610
return dataType_;
00611 }
00612
00613
00614
00615
00616 void VarItem::paintCell(
QPainter *p,
const QColorGroup &cg,
00617
int column,
int width,
int align)
00618 {
00619
if ( !p )
00620
return;
00621
00622
if (column == ValueCol &&
highlight_) {
00623
QColorGroup hl_cg( cg.foreground(), cg.background(), cg.light(),
00624 cg.dark(), cg.mid(), red, cg.base());
00625 QListViewItem::paintCell( p, hl_cg, column, width, align );
00626 }
else
00627 QListViewItem::paintCell( p, cg, column, width, align );
00628 }
00629
00630
00631
00632
00633
00634 FrameRoot::FrameRoot(
VariableTree *parent,
int frameNo)
00635 :
TrimmableItem (parent),
00636 needLocals_(true),
00637 frameNo_(frameNo),
00638 params_(
QCString()),
00639 locals_(
QCString())
00640 {
00641 setExpandable(
true);
00642 }
00643
00644
00645
00646 FrameRoot::~FrameRoot()
00647 {
00648 }
00649
00650
00651
00652 void FrameRoot::addLocal(
QString name,
QString ,
QString )
00653 {
00654 setText( VarNameCol, name);
00655 }
00656
00657
00658 void FrameRoot::setLocals(
char *locals)
00659 {
00660 Q_ASSERT(
isActive());
00661
00662
00663
bool noLocals = (locals && (strncmp(locals,
"No ", 3) == 0));
00664 setExpandable(!
params_.isEmpty() || !noLocals);
00665
00666
if (noLocals) {
00667
locals_ =
"";
00668
if (locals)
00669
if (
char *end = strchr(locals,
'\n'))
00670 *end = 0;
00671 }
else
00672
locals_ = locals;
00673
00674
if (!isExpandable() && noLocals)
00675 setText( ValueCol, locals );
00676
00677
needLocals_ =
false;
00678
if (isOpen())
00679
setOpen(
true);
00680 }
00681
00682
00683
00684 void FrameRoot::setParams(
const QCString ¶ms)
00685 {
00686
setActive();
00687
params_ = params;
00688
needLocals_ =
true;
00689 }
00690
00691
00692
00693
00694
00695 void FrameRoot::setOpen(
bool open)
00696 {
00697
bool localStateChange = (isOpen() != open);
00698 QListViewItem::setOpen(open);
00699
00700
if (localStateChange)
00701 ((
VariableTree*)listView())->setLocalViewState(open,
frameNo_);
00702
00703
if (!open)
00704
return;
00705
00706
getParser()->
parseData(
this,
params_.data(),
false,
true);
00707
getParser()->
parseData(
this,
locals_.data(),
false,
false);
00708
00709
locals_ =
QCString();
00710
params_ = QCString();
00711 }
00712
00713
00714
00715
00716
00717
00718 WatchRoot::WatchRoot(
VariableTree *parent)
00719 :
TrimmableItem(parent)
00720 {
00721 setText(0, i18n(
"Watch"));
00722 setOpen(
true);
00723 }
00724
00725
00726
00727 WatchRoot::~WatchRoot()
00728 {
00729 }
00730
00731
00732
00733 void WatchRoot::requestWatchVars()
00734 {
00735
for (
QListViewItem *child = firstChild(); child; child = child->nextSibling())
00736
if (
VarItem *varItem = dynamic_cast<VarItem*>(child))
00737 emit ((
VariableTree*)listView())->expandItem(varItem);
00738 }
00739
00740
00741
00742
00743
00744 }
00745
00746
#include "variablewidget.moc"