~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to languages/ruby/debugger/variablewidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2006-05-23 18:39:42 UTC
  • Revision ID: james.westby@ubuntu.com-20060523183942-hucifbvh68k2bwz7
Tags: upstream-3.3.2
Import upstream version 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// **************************************************************************
 
2
//    begin                : Sun Aug 8 1999
 
3
//    copyright            : (C) 1999 by John Birch
 
4
//    email                : jbb@kdevelop.org
 
5
//      
 
6
//                          Adapted for ruby debugging
 
7
//                          --------------------------
 
8
//    begin                : Mon Nov 1 2004
 
9
//    copyright            : (C) 2004 by Richard Dale
 
10
//    email                : Richard_Dale@tipitina.demon.co.uk
 
11
// **************************************************************************
 
12
 
 
13
// **************************************************************************
 
14
// *                                                                        *
 
15
// *   This program is free software; you can redistribute it and/or modify *
 
16
// *   it under the terms of the GNU General Public License as published by *
 
17
// *   the Free Software Foundation; either version 2 of the License, or    *
 
18
// *   (at your option) any later version.                                  *
 
19
// *                                                                        *
 
20
// **************************************************************************
 
21
 
 
22
#include "variablewidget.h"
 
23
#include "rdbparser.h"
 
24
#include "rdbcommand.h"
 
25
 
 
26
#include <kdebug.h>
 
27
#include <kpopupmenu.h>
 
28
#include <klineedit.h>
 
29
#include <kdeversion.h>
 
30
 
 
31
#include <qheader.h>
 
32
#include <qlabel.h>
 
33
#include <qlayout.h>
 
34
#include <qhbox.h>
 
35
#include <qpainter.h>
 
36
#include <qpushbutton.h>
 
37
#include <qregexp.h>
 
38
#include <qcursor.h>
 
39
#include <klocale.h>
 
40
 
 
41
#include <qpoint.h>
 
42
#include <qclipboard.h>
 
43
#include <kapplication.h>
 
44
 
 
45
// **************************************************************************
 
46
// **************************************************************************
 
47
// **************************************************************************
 
48
 
 
49
namespace RDBDebugger
 
50
{
 
51
 
 
52
VariableWidget::VariableWidget(QWidget *parent, const char *name)
 
53
    : QWidget(parent, name)
 
54
{
 
55
    varTree_ = new VariableTree(this);
 
56
    QLabel *label = new QLabel(i18n("E&xpression to watch:"), this);
 
57
 
 
58
    QHBox *watchEntry = new QHBox( this );
 
59
    watchVarEditor_ = new KHistoryCombo( watchEntry, "var-to-watch editor");
 
60
    label->setBuddy(watchVarEditor_);
 
61
 
 
62
    QPushButton *addButton = new QPushButton(i18n("&Add"), watchEntry );
 
63
    addButton->adjustSize();
 
64
    addButton->setFixedWidth(addButton->width());
 
65
 
 
66
    QBoxLayout * vbox = new QVBoxLayout();
 
67
    vbox->addWidget( label );
 
68
    vbox->addWidget( watchEntry );
 
69
 
 
70
    QVBoxLayout *topLayout = new QVBoxLayout(this, 2);
 
71
    topLayout->addWidget(varTree_, 10);
 
72
    topLayout->addLayout( vbox );
 
73
 
 
74
    connect( addButton, SIGNAL(clicked()), SLOT(slotAddWatchExpression()) );
 
75
    connect( watchVarEditor_, SIGNAL(returnPressed()), SLOT(slotAddWatchExpression()) );
 
76
}
 
77
 
 
78
 
 
79
// **************************************************************************
 
80
 
 
81
void VariableWidget::setEnabled(bool bEnabled)
 
82
{
 
83
    QWidget::setEnabled(bEnabled);
 
84
    if (bEnabled && parentWidget() != 0) {
 
85
        varTree_->setColumnWidth(0, parentWidget()->width()/2);
 
86
        }
 
87
}
 
88
// **************************************************************************
 
89
 
 
90
void VariableWidget::slotAddWatchExpression()
 
91
{
 
92
    QString watchVar(watchVarEditor_->currentText());
 
93
    if (!watchVar.isEmpty()) {
 
94
        slotAddWatchExpression(watchVar);
 
95
    }
 
96
}
 
97
 
 
98
// **************************************************************************
 
99
 
 
100
void VariableWidget::slotAddWatchExpression(const QString &ident)
 
101
{
 
102
    if (!ident.isEmpty()) {
 
103
        watchVarEditor_->addToHistory(ident);
 
104
        varTree_->slotAddWatchExpression(ident);
 
105
        watchVarEditor_->clearEdit();
 
106
    }
 
107
}
 
108
 
 
109
// **************************************************************************
 
110
 
 
111
void VariableWidget::focusInEvent(QFocusEvent */*e*/)
 
112
{
 
113
    varTree_->setFocus();
 
114
}
 
115
 
 
116
void VariableWidget::restorePartialProjectSession(const QDomElement* el)
 
117
{
 
118
        varTree_->watchRoot()->restorePartialProjectSession(el);
 
119
}
 
120
 
 
121
void VariableWidget::savePartialProjectSession(QDomElement* el)
 
122
{
 
123
        varTree_->watchRoot()->savePartialProjectSession(el);
 
124
}
 
125
 
 
126
// **************************************************************************
 
127
// **************************************************************************
 
128
// **************************************************************************
 
129
 
 
130
VariableTree::VariableTree(VariableWidget *parent, const char *name)
 
131
    : KListView(parent, name),
 
132
      QToolTip( viewport() ),
 
133
      activationId_(0),
 
134
      currentThread_(-1),
 
135
          selectedFrame_(0),
 
136
          watchRoot_(0),
 
137
          globalRoot_(0)
 
138
{
 
139
    setRootIsDecorated(true);
 
140
    setAllColumnsShowFocus(true);
 
141
    setColumnWidthMode(0, Manual);
 
142
    setSorting(VAR_NAME_COLUMN);
 
143
    QListView::setSelectionMode(QListView::Single);
 
144
 
 
145
    addColumn(i18n("Variable"), 100 );
 
146
    addColumn(i18n("Value"), 100 );
 
147
 
 
148
    connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
 
149
             SLOT(slotContextMenu(KListView*, QListViewItem*)) );
 
150
    
 
151
        connect( this, SIGNAL(pressed(QListViewItem*)),
 
152
             this, SLOT(slotPressed(QListViewItem*)) );
 
153
 
 
154
        watchRoot_ = new WatchRoot(this);
 
155
}
 
156
 
 
157
// **************************************************************************
 
158
 
 
159
VariableTree::~VariableTree()
 
160
{
 
161
}
 
162
 
 
163
// **************************************************************************
 
164
 
 
165
void VariableTree::clear()
 
166
{
 
167
    QListViewItem *sibling = firstChild();
 
168
    while (sibling != 0) {
 
169
                QListViewItem * current = sibling;
 
170
                sibling = sibling->nextSibling();
 
171
                if (current->rtti() != RTTI_WATCH_ROOT) {
 
172
                        delete current;
 
173
                }
 
174
    }
 
175
        
 
176
        globalRoot_ = 0;
 
177
        selectedFrame_ = 0;
 
178
        return;
 
179
}
 
180
 
 
181
// **************************************************************************
 
182
 
 
183
void VariableTree::slotContextMenu(KListView *, QListViewItem *item)
 
184
{
 
185
    if (item == 0)
 
186
        return;
 
187
 
 
188
    setSelected(item, true);    // Need to select this item.
 
189
 
 
190
    if (item->parent() != 0) {
 
191
        KPopupMenu popup(this);
 
192
        popup.insertTitle(item->text(VAR_NAME_COLUMN));
 
193
        int idRemoveWatch = -2;
 
194
        if (item->rtti() == RTTI_WATCH_VAR_ITEM) {
 
195
            idRemoveWatch = popup.insertItem( i18n("Remove Watch Expression") );
 
196
                }
 
197
 
 
198
        int     idCopyToClipboard = popup.insertItem( i18n("Copy to Clipboard") );
 
199
        int res = popup.exec(QCursor::pos());
 
200
 
 
201
        if (res == idRemoveWatch) {
 
202
                        emit removeWatchExpression(((WatchVarItem*)item)->displayId());
 
203
            delete item;
 
204
        } else if (res == idCopyToClipboard) {
 
205
            QClipboard *qb = KApplication::clipboard();
 
206
            QString text = "{ \"" + item->text( VAR_NAME_COLUMN ) + "\", " +
 
207
                            "\"" + item->text( VALUE_COLUMN ) + "\" }";
 
208
 
 
209
#if KDE_VERSION > 305
 
210
            qb->setText( text, QClipboard::Clipboard );
 
211
#else
 
212
            qb->setText( text );
 
213
#endif
 
214
        }
 
215
    }
 
216
}
 
217
 
 
218
/***************************************************************************/
 
219
 
 
220
void VariableTree::setSelected(QListViewItem * item, bool selected)
 
221
{
 
222
        // Save the last selected VarFrameRoot for slotPressed() to restore
 
223
        if (item->rtti() == RTTI_VAR_FRAME_ROOT && selected) {
 
224
                selectedFrame_ = (VarFrameRoot *) item;
 
225
        }
 
226
        
 
227
        QListView::setSelected(item, selected);
 
228
}
 
229
 
 
230
/***************************************************************************/
 
231
 
 
232
// Makes sure that only VarFrameRoot items can be selected
 
233
void VariableTree::slotPressed(QListViewItem * item)
 
234
{
 
235
        if (item == 0) {
 
236
                return;
 
237
        }
 
238
        
 
239
        while (item->rtti() == RTTI_VAR_ITEM) {
 
240
                item = item->parent();
 
241
        }
 
242
        
 
243
        if (    item->rtti() == RTTI_GLOBAL_ROOT
 
244
                        || item->rtti() == RTTI_WATCH_ROOT
 
245
                        || item->rtti() == RTTI_WATCH_VAR_ITEM )
 
246
        {
 
247
                if (selectedFrame_ != 0) {
 
248
                        setSelected(selectedFrame_, true);
 
249
                }
 
250
                return;
 
251
        }
 
252
        
 
253
        if (item->rtti() == RTTI_VAR_FRAME_ROOT) {
 
254
                VarFrameRoot * frame = (VarFrameRoot*) item;
 
255
        emit selectFrame(frame->frameNo(), frame->threadNo());
 
256
        }
 
257
        
 
258
        return;
 
259
}
 
260
 
 
261
// **************************************************************************
 
262
 
 
263
void VariableTree::prune()
 
264
{
 
265
        QListViewItem *child = firstChild();
 
266
 
 
267
    while (child != 0) {
 
268
        QListViewItem *nextChild = child->nextSibling();
 
269
 
 
270
        // Only prune var frames, not the watch or global root
 
271
        if (child->rtti() == RTTI_VAR_FRAME_ROOT) {
 
272
                        if (((VarFrameRoot*) child)->isActive()) {
 
273
                                if (child->isOpen()) {
 
274
                                        ((VarFrameRoot*) child)->prune();
 
275
                                }
 
276
                        } else {
 
277
                                delete child;
 
278
                        }
 
279
                }
 
280
                
 
281
        child = nextChild;
 
282
    }
 
283
}
 
284
 
 
285
// **************************************************************************
 
286
 
 
287
// The debugger has moved onto the next program pause, so invalidate 
 
288
// everything in the Variable Tree
 
289
void VariableTree::nextActivationId() 
 
290
 
291
        activationId_++; 
 
292
        globalRoot()->setActivationId();
 
293
        watchRoot()->setActivationId();
 
294
        // ..but that's only the Watch and Global roots
 
295
}
 
296
    
 
297
// **************************************************************************
 
298
 
 
299
// VarFrameRoot frames in the Variable Tree from the previous program pause, 
 
300
// are set active here. Notified by the Frame Stack widget when it parses the 
 
301
// backtrace from the 'where' command after a pause.
 
302
//
 
303
// After that, any frames which aren't marked as active must have gone
 
304
// out of scope and will end up pruned.
 
305
void VariableTree::slotFrameActive(int frameNo, int threadNo, const QString& frameName)
 
306
{
 
307
        VarFrameRoot * frame = findFrame(frameNo, threadNo);
 
308
        if (frameNo == 1) {
 
309
                // If the current frame 1 doesn't exist, create it
 
310
                if (frame == 0) {
 
311
                        frame = new VarFrameRoot(this, frameNo, threadNo);
 
312
                }
 
313
                
 
314
                frame->setFrameName(frameName);
 
315
        }
 
316
        
 
317
        if (frame != 0 && frame->text(VAR_NAME_COLUMN) == frameName) {
 
318
                frame->setActivationId();
 
319
        }
 
320
}
 
321
 
 
322
// **************************************************************************
 
323
 
 
324
bool VariableTree::schedule()
 
325
{
 
326
    QListViewItem *     child = firstChild();
 
327
        VarFrameRoot * frame = 0;
 
328
 
 
329
    while (child != 0) {
 
330
        if (child->rtti() == RTTI_VAR_FRAME_ROOT) {
 
331
                        frame = (VarFrameRoot *) child;
 
332
                        Q_ASSERT( !frame->isWaitingForData() );
 
333
                        
 
334
                        if (frame->needsVariables()) {
 
335
                                if (QApplication::overrideCursor() == 0) {
 
336
                                        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
337
                                }
 
338
                                
 
339
                                // Tell the controller to fetch the variable values
 
340
                                emit selectFrame(frame->frameNo(), frame->threadNo());
 
341
                                return true;
 
342
                        }
 
343
                }
 
344
                
 
345
        child = child->nextSibling();
 
346
    }
 
347
        
 
348
        frame = findFrame(1, currentThread_);
 
349
        Q_ASSERT( frame != 0 );
 
350
        Q_ASSERT( !frame->needsVariables() );
 
351
                
 
352
        // All over, nothing left to fetch. 
 
353
        // Return to frame 1, and prune the inactive items
 
354
        // from the variable tree..
 
355
        QApplication::restoreOverrideCursor();
 
356
        emit selectFrame(1, currentThread_);
 
357
        prune();
 
358
        
 
359
        return false;
 
360
}
 
361
 
 
362
// **************************************************************************
 
363
 
 
364
void VariableTree::slotAddWatchExpression(const QString &watchVar)
 
365
{
 
366
    new WatchVarItem(watchRoot(), watchVar, UNKNOWN_TYPE);
 
367
        emit addWatchExpression(watchVar, true);
 
368
}
 
369
 
 
370
 
 
371
// **************************************************************************
 
372
 
 
373
void VariableTree::setFetchGlobals(bool fetch)
 
374
{
 
375
        emit fetchGlobals(fetch);
 
376
}
 
377
 
 
378
// **************************************************************************
 
379
 
 
380
VarFrameRoot *VariableTree::findFrame(int frameNo, int threadNo) const
 
381
{
 
382
    // frames only exist on the top level so we only need to
 
383
    // check the siblings
 
384
    QListViewItem *sibling = firstChild();
 
385
    while (sibling != 0) {
 
386
                if (    sibling->rtti() == RTTI_VAR_FRAME_ROOT
 
387
                                && ((VarFrameRoot*) sibling)->frameNo() == frameNo 
 
388
                                && ((VarFrameRoot*) sibling)->threadNo() == threadNo ) 
 
389
                {
 
390
                        return (VarFrameRoot*) sibling;
 
391
                }
 
392
                
 
393
        sibling = sibling->nextSibling();
 
394
    }
 
395
 
 
396
    return 0;
 
397
}
 
398
 
 
399
// **************************************************************************
 
400
 
 
401
WatchRoot *VariableTree::watchRoot()
 
402
{
 
403
    return watchRoot_;
 
404
}
 
405
 
 
406
// **************************************************************************
 
407
 
 
408
GlobalRoot *VariableTree::globalRoot()
 
409
{
 
410
        if (globalRoot_ == 0) {
 
411
                globalRoot_ = new GlobalRoot(this);
 
412
        }
 
413
 
 
414
    return globalRoot_;
 
415
}
 
416
 
 
417
// **************************************************************************
 
418
 
 
419
// Watch variables can be added before the start of a debugging session,
 
420
// so tell the controller about any already in the tree at start.
 
421
void VariableTree::resetWatchVars()
 
422
{
 
423
        for (QListViewItem *child = watchRoot()->firstChild(); child != 0; child = child->nextSibling()) {
 
424
                ((WatchVarItem*) child)->setDisplayId(-1);
 
425
        emit addWatchExpression(child->text(VAR_NAME_COLUMN), false);
 
426
        }
 
427
}
 
428
 
 
429
// **************************************************************************
 
430
 
 
431
void VariableTree::maybeTip(const QPoint &p)
 
432
{
 
433
    VarItem * item = dynamic_cast<VarItem*>( itemAt(p) );
 
434
    if (item != 0) {
 
435
        QRect r = itemRect(item);
 
436
        if (r.isValid()) {
 
437
            tip(r, item->tipText());
 
438
                }
 
439
    }
 
440
}
 
441
 
 
442
 
 
443
// **************************************************************************
 
444
// **************************************************************************
 
445
// **************************************************************************
 
446
 
 
447
LazyFetchItem::LazyFetchItem(VariableTree *parent)
 
448
    : KListViewItem(parent),
 
449
      activationId_(0),
 
450
          waitingForData_(false)
 
451
{
 
452
    setActivationId();
 
453
}
 
454
 
 
455
// **************************************************************************
 
456
 
 
457
LazyFetchItem::LazyFetchItem(LazyFetchItem *parent)
 
458
    : KListViewItem(parent),
 
459
      activationId_(0),
 
460
      waitingForData_(false)
 
461
{
 
462
    setActivationId();
 
463
}
 
464
 
 
465
// **************************************************************************
 
466
 
 
467
LazyFetchItem::~LazyFetchItem()
 
468
{
 
469
}
 
470
 
 
471
// **************************************************************************
 
472
 
 
473
void LazyFetchItem::paintCell(QPainter *p, const QColorGroup &cg,
 
474
                              int column, int width, int align)
 
475
{
 
476
    if (p == 0) {
 
477
        return;
 
478
        }
 
479
        
 
480
    // make toplevel item (watch and frame items) names bold
 
481
    if (column == VAR_NAME_COLUMN && parent() == 0) {
 
482
        QFont f = p->font();
 
483
        f.setBold(true);
 
484
        p->setFont(f);
 
485
    }
 
486
        
 
487
    QListViewItem::paintCell( p, cg, column, width, align );
 
488
}
 
489
 
 
490
// **************************************************************************
 
491
 
 
492
VarItem *LazyFetchItem::findItem(const QString &name) const
 
493
{
 
494
        QListViewItem *child = firstChild();
 
495
 
 
496
    // Check the siblings on this branch
 
497
    while (child != 0) {
 
498
                if (child->text(VAR_NAME_COLUMN) == name) {
 
499
                        return (VarItem*) child;
 
500
                }
 
501
 
 
502
        child = child->nextSibling();
 
503
    }
 
504
 
 
505
    return 0;
 
506
}
 
507
 
 
508
// **************************************************************************
 
509
 
 
510
void LazyFetchItem::prune()
 
511
{
 
512
    QListViewItem *child = firstChild();
 
513
 
 
514
    while (child != 0) {
 
515
        LazyFetchItem *item = (LazyFetchItem*) child;
 
516
        child = child->nextSibling();
 
517
                // Never prune a branch if we are waiting on data to arrive.
 
518
                if (!waitingForData_) {
 
519
                        if (item->isActive()) {
 
520
                                item->prune();
 
521
                        } else {
 
522
                                delete item;
 
523
                        }
 
524
        }
 
525
    }
 
526
}
 
527
 
 
528
 
 
529
// **************************************************************************
 
530
// **************************************************************************
 
531
// **************************************************************************
 
532
 
 
533
VarItem::VarItem(LazyFetchItem *parent, const QString &varName, DataType dataType)
 
534
    : LazyFetchItem (parent),
 
535
      cache_(QCString()),
 
536
      dataType_(dataType),
 
537
      highlight_(false)
 
538
{
 
539
    setText(VAR_NAME_COLUMN, varName);
 
540
        setSelectable(false);
 
541
        
 
542
        // Order the VarItems so that globals are first, then
 
543
        // constants, class variables, instance variables and 
 
544
        // finally local variables
 
545
        
 
546
        // Matches either an array element or a string slice,
 
547
        // Order on the array index or the first number in the
 
548
        // range specifying the slice.
 
549
        QRegExp arrayelement_re("\\[(\\d+)(\\.\\.\\d+)?\\]");
 
550
        key_ = varName;
 
551
        
 
552
        if (arrayelement_re.search(varName) != -1) {
 
553
                key_.sprintf("%.6d", arrayelement_re.cap(1).toInt());
 
554
        } else if (key_.startsWith("$")) {
 
555
                key_.prepend("1001");           // Global variable
 
556
        } else if (QRegExp("^[A-Z]").search(varName) != -1) {
 
557
                key_.prepend("1002");           // Constant
 
558
        } else if (key_.startsWith("@@")) {
 
559
                key_.prepend("1003");           // Class variable
 
560
        } else if (key_.startsWith("@")) {
 
561
                key_.prepend("1004");           // Instance variable
 
562
        } else {
 
563
                key_.prepend("1005");           // Local variable or parameter
 
564
        }
 
565
 
 
566
//    kdDebug(9012) << " ### VarItem::VarItem *CONSTR* " << varName << endl;    
 
567
}
 
568
 
 
569
// **************************************************************************
 
570
 
 
571
VarItem::~VarItem()
 
572
{
 
573
}
 
574
 
 
575
QString VarItem::key(int /*column*/, bool /*ascending*/) const 
 
576
{
 
577
        return key_;
 
578
}
 
579
 
 
580
// **************************************************************************
 
581
 
 
582
// Returns the path of a ruby item. If it is an instance variable, assume
 
583
// that there is an attr_accessor method for it.
 
584
// For example, @foobar within instance obj is accessed as obj.foobar.
 
585
// But don't strip off the @ for an instance variable with no path,
 
586
// and leave a plain '@foobar' as it is.
 
587
QString VarItem::fullName() const
 
588
{
 
589
        QString itemName = text(VAR_NAME_COLUMN);
 
590
    QString vPath("");
 
591
    const VarItem *item = this;
 
592
 
 
593
        if (item->parent()->rtti() != RTTI_VAR_ITEM) {
 
594
                return itemName;
 
595
        }
 
596
 
 
597
    // This stops at the root item (FrameRoot or GlobalRoot)
 
598
        while (item->rtti() == RTTI_VAR_ITEM) {
 
599
                QString itemName = item->text(VAR_NAME_COLUMN);
 
600
                
 
601
                if (vPath.startsWith("[")) {
 
602
                        // If it's a Hash or an Array, then just insert the value. As
 
603
                        // in adding '[0]' to foo.bar to give foo.bar[0]
 
604
                        vPath.prepend(itemName);
 
605
                } else {
 
606
                        if (vPath.isEmpty()) {
 
607
                                vPath = itemName;
 
608
                        } else {
 
609
                                vPath.prepend(itemName + ".");
 
610
                        }
 
611
        }
 
612
                item = (VarItem*) item->parent();
 
613
    }
 
614
 
 
615
        // Change 'self.@foobar' to '@foobar'
 
616
        vPath.replace(QRegExp("^self\\.@"), "@");
 
617
        
 
618
        // Use instance_variable_get() to access any '@var's in the middle of a path    
 
619
        QRegExp re_instance_var("\\.(@[^.]+)");
 
620
        int pos = re_instance_var.search(vPath);        
 
621
        while (pos != -1) {     
 
622
                vPath.replace(  pos, 
 
623
                                                re_instance_var.matchedLength(), 
 
624
                                                QString(".instance_variable_get(:") + re_instance_var.cap(1) + ")" );
 
625
                pos = re_instance_var.search(vPath, pos);       
 
626
        }               
 
627
 
 
628
    return vPath;
 
629
}
 
630
 
 
631
// **************************************************************************
 
632
 
 
633
void VarItem::setText(int column, const QString &data)
 
634
{
 
635
        setActivationId();
 
636
        
 
637
    if (column == VALUE_COLUMN) {
 
638
                highlight_ = (!text(VALUE_COLUMN).isEmpty() && text(VALUE_COLUMN) != data);
 
639
    }
 
640
 
 
641
    QListViewItem::setText(column, data);
 
642
    repaint();
 
643
}
 
644
 
 
645
// **************************************************************************
 
646
 
 
647
void VarItem::expandValue(char *buf)
 
648
{
 
649
    LazyFetchItem::stopWaitingForData();
 
650
    RDBParser::parseExpandedVariable(this, buf);
 
651
}
 
652
 
 
653
// **************************************************************************
 
654
 
 
655
void VarItem::setOpen(bool open)
 
656
{
 
657
    QListViewItem::setOpen(open);
 
658
        
 
659
        Q_ASSERT(       dataType_ == REFERENCE_TYPE 
 
660
                                || dataType_ == ARRAY_TYPE 
 
661
                                || dataType_ == HASH_TYPE
 
662
                                || dataType_ == STRING_TYPE
 
663
                                || dataType_ == STRUCT_TYPE );
 
664
                                        
 
665
        update();
 
666
        return;
 
667
}
 
668
 
 
669
// **************************************************************************
 
670
 
 
671
void VarItem::update()
 
672
{
 
673
        if (isOpen()) {
 
674
                startWaitingForData();
 
675
//              emit ((VariableTree*)listView())->expandItem(this, fullName().latin1());
 
676
                ((VariableTree*)listView())->expandItem(this, fullName().latin1());
 
677
        }
 
678
 
 
679
        return;
 
680
}
 
681
 
 
682
// **************************************************************************
 
683
 
 
684
DataType VarItem::dataType() const
 
685
{
 
686
    return dataType_;
 
687
}
 
688
 
 
689
// **************************************************************************
 
690
 
 
691
void VarItem::setDataType(DataType dataType)
 
692
{
 
693
    dataType_ = dataType;
 
694
}
 
695
 
 
696
// **************************************************************************
 
697
 
 
698
// Overridden to highlight the changed items
 
699
void VarItem::paintCell(QPainter *p, const QColorGroup &cg,
 
700
                        int column, int width, int align)
 
701
{
 
702
    if (p == 0) {
 
703
        return;
 
704
        }
 
705
 
 
706
    if (column == VALUE_COLUMN) {
 
707
                // Show color values as colors, and make the text color the same
 
708
                // as the base color
 
709
                if (dataType_ == COLOR_TYPE) {
 
710
                        QRegExp color_re("\\s(#.*)>");
 
711
                        
 
712
                        if (color_re.search(text(column)) != -1) {
 
713
                        QColorGroup color_cg(   cg.foreground(), cg.background(), 
 
714
                                                                                cg.light(), cg.dark(), cg.mid(), 
 
715
                                                                                QColor(color_re.cap(1)), QColor(color_re.cap(1)) );
 
716
                        QListViewItem::paintCell(p, color_cg, column, width, align);
 
717
                                return;
 
718
                        }
 
719
                }
 
720
                
 
721
                // Highlight recently changed items in red
 
722
                if (highlight_) {
 
723
                QColorGroup hl_cg(      cg.foreground(), cg.background(), 
 
724
                                                                cg.light(), cg.dark(), cg.mid(), 
 
725
                                                                red, cg.base() );
 
726
                QListViewItem::paintCell(p, hl_cg, column, width, align);
 
727
                        return;
 
728
                }
 
729
        }
 
730
        
 
731
        QListViewItem::paintCell(p, cg, column, width, align);
 
732
        return;
 
733
}
 
734
 
 
735
// **************************************************************************
 
736
 
 
737
QString VarItem::tipText() const
 
738
{
 
739
    const unsigned int MAX_TOOLTIP_SIZE = 70;
 
740
    QString tip = text(VALUE_COLUMN);
 
741
 
 
742
    if (tip.length() < MAX_TOOLTIP_SIZE) {
 
743
            return tip;
 
744
    } else {
 
745
            return tip.mid(0, MAX_TOOLTIP_SIZE - 1) + " [...]";
 
746
        }
 
747
}
 
748
 
 
749
// **************************************************************************
 
750
// **************************************************************************
 
751
// **************************************************************************
 
752
 
 
753
VarFrameRoot::VarFrameRoot(VariableTree *parent, int frameNo, int threadNo)
 
754
    : LazyFetchItem(parent),
 
755
      needsVariables_(true),
 
756
      frameNo_(frameNo),
 
757
      threadNo_(threadNo),
 
758
      cache_("")
 
759
{
 
760
    setExpandable(true);
 
761
}
 
762
 
 
763
// **************************************************************************
 
764
 
 
765
VarFrameRoot::~VarFrameRoot()
 
766
{
 
767
}
 
768
 
 
769
// **************************************************************************
 
770
 
 
771
void VarFrameRoot::addLocals(char *variables)
 
772
{
 
773
    cache_.append(variables);
 
774
}
 
775
 
 
776
// **************************************************************************
 
777
 
 
778
void VarFrameRoot::setLocals()
 
779
{
 
780
    RDBParser::parseVariables(this, cache_.data());
 
781
        cache_ = "";
 
782
    needsVariables_ = false;
 
783
        stopWaitingForData();
 
784
        prune();
 
785
        
 
786
        return;
 
787
}
 
788
 
 
789
// **************************************************************************
 
790
 
 
791
// Override setOpen so that we can decide what to do when we do change
 
792
// state.
 
793
void VarFrameRoot::setOpen(bool open)
 
794
{
 
795
        bool localsViewChanged = (isOpen() != open);
 
796
    QListViewItem::setOpen(open);
 
797
        
 
798
    if (localsViewChanged) {
 
799
                ((VariableTree*)listView())->selectFrame(frameNo_, threadNo_);
 
800
        }
 
801
 
 
802
        return;
 
803
}
 
804
 
 
805
void VarFrameRoot::setFrameName(const QString &frameName)
 
806
{
 
807
        setText(VAR_NAME_COLUMN, frameName); 
 
808
        setText(VALUE_COLUMN, "");
 
809
        
 
810
        return; 
 
811
}
 
812
 
 
813
void VarFrameRoot::setActivationId() 
 
814
 
815
        LazyFetchItem::setActivationId(); 
 
816
        stopWaitingForData();
 
817
        needsVariables_ = true;
 
818
        cache_ = "";
 
819
 
820
        
 
821
bool VarFrameRoot::needsVariables() const 
 
822
 
823
        return (        text(VAR_NAME_COLUMN).contains("try_initialize") == 0 
 
824
                                && isOpen() 
 
825
                                && !isWaitingForData() 
 
826
                                && needsVariables_ ); 
 
827
}
 
828
 
 
829
// **************************************************************************
 
830
// **************************************************************************
 
831
// **************************************************************************
 
832
// **************************************************************************
 
833
 
 
834
 
 
835
GlobalRoot::GlobalRoot(VariableTree *parent)
 
836
    : LazyFetchItem(parent)
 
837
{
 
838
    setText(0, i18n("Global"));
 
839
    setExpandable(true);
 
840
    setOpen(false);
 
841
        setSelectable(false);
 
842
}
 
843
 
 
844
// **************************************************************************
 
845
 
 
846
GlobalRoot::~GlobalRoot()
 
847
{
 
848
}
 
849
 
 
850
// **************************************************************************
 
851
 
 
852
void GlobalRoot::setGlobals(char * globals)
 
853
{
 
854
    setActivationId();
 
855
    RDBParser::parseVariables(this, globals);
 
856
        
 
857
        return;
 
858
}
 
859
 
 
860
// **************************************************************************
 
861
 
 
862
void GlobalRoot::setOpen(bool open)
 
863
{
 
864
        bool globalsViewChanged = (isOpen() != open);
 
865
        QListViewItem::setOpen(open);
 
866
        
 
867
        if (globalsViewChanged) {
 
868
        ((VariableTree*)listView())->setFetchGlobals(isOpen());
 
869
        }
 
870
        
 
871
        return;
 
872
}
 
873
 
 
874
// **************************************************************************
 
875
// **************************************************************************
 
876
// **************************************************************************
 
877
// **************************************************************************
 
878
 
 
879
WatchVarItem::WatchVarItem( LazyFetchItem *parent, const QString &varName, DataType dataType, int displayId )
 
880
    : VarItem(parent, varName, dataType),
 
881
        displayId_(displayId)
 
882
{
 
883
}
 
884
 
 
885
// **************************************************************************
 
886
 
 
887
WatchVarItem::~WatchVarItem()
 
888
{
 
889
}
 
890
 
 
891
// **************************************************************************
 
892
 
 
893
void WatchVarItem::setDisplayId(int id)
 
894
{
 
895
        displayId_ = id;
 
896
}
 
897
 
 
898
// **************************************************************************
 
899
 
 
900
int WatchVarItem::displayId()
 
901
{
 
902
        return displayId_;
 
903
}
 
904
 
 
905
// **************************************************************************
 
906
// **************************************************************************
 
907
// **************************************************************************
 
908
// **************************************************************************
 
909
 
 
910
WatchRoot::WatchRoot(VariableTree *parent)
 
911
    : LazyFetchItem(parent)
 
912
{
 
913
    setText(VAR_NAME_COLUMN, i18n("Watch"));
 
914
    setOpen(true);
 
915
        setSelectable(false);
 
916
}
 
917
 
 
918
// **************************************************************************
 
919
 
 
920
WatchRoot::~WatchRoot()
 
921
{
 
922
}
 
923
 
 
924
// **************************************************************************
 
925
 
 
926
// Sets the initial value of a new Watch item, along with the
 
927
// display id
 
928
void WatchRoot::setWatchExpression(char * buf, char * expression)
 
929
{
 
930
        QString expr(expression);
 
931
        QRegExp display_re("^(\\d+):\\s([^\n]+)\n");
 
932
        
 
933
    for (       QListViewItem *child = firstChild(); 
 
934
                        child != 0; 
 
935
                        child = child->nextSibling() ) 
 
936
        {
 
937
        WatchVarItem *varItem = (WatchVarItem*) child;
 
938
                if (    varItem->text(VAR_NAME_COLUMN) == expr 
 
939
                                && varItem->displayId() == -1
 
940
                                && display_re.search(buf) >= 0 ) 
 
941
                {
 
942
                        varItem->setDisplayId(display_re.cap(1).toInt());
 
943
                        // Skip over the 'thing = ' part of expr to get the value
 
944
                        varItem->setText(       VALUE_COLUMN, 
 
945
                                                                display_re.cap(2).mid(varItem->text(VAR_NAME_COLUMN).length() + strlen(" = ")) );
 
946
                        return;
 
947
                }
 
948
        }
 
949
}
 
950
 
 
951
// After a program pause, this updates the new value of a Watch item
 
952
// expr is the thing = value part of "1: a = 1", id is the display number
 
953
void WatchRoot::updateWatchExpression(int id, const QString& expr)
 
954
{
 
955
    for (       QListViewItem *child = firstChild(); 
 
956
                        child != 0; 
 
957
                        child = child->nextSibling() ) 
 
958
        {
 
959
        WatchVarItem *varItem = (WatchVarItem*) child;
 
960
                if (varItem->displayId() == id) {
 
961
                        Q_ASSERT( expr.startsWith(varItem->text(VAR_NAME_COLUMN)) );
 
962
                        // Skip over the 'thing = ' part of expr to get the value
 
963
                        varItem->setText(       VALUE_COLUMN, 
 
964
                                                                expr.mid(varItem->text(VAR_NAME_COLUMN).length() + strlen(" = ")) );
 
965
                        return;
 
966
                }
 
967
        }
 
968
}
 
969
 
 
970
void WatchRoot::savePartialProjectSession(QDomElement* el)
 
971
{
 
972
    QDomDocument domDoc = el->ownerDocument();
 
973
    if (domDoc.isNull()) {
 
974
        return;
 
975
        }
 
976
        
 
977
    QDomElement watchEl = domDoc.createElement("watchExpressions");
 
978
    
 
979
        for (   QListViewItem *child = firstChild(); 
 
980
                        child != 0; 
 
981
                        child = child->nextSibling() )
 
982
        {
 
983
        QDomElement subEl = domDoc.createElement("el");
 
984
        subEl.appendChild(domDoc.createTextNode(child->text(VAR_NAME_COLUMN)));
 
985
        watchEl.appendChild(subEl);
 
986
        }
 
987
        
 
988
    if (!watchEl.isNull()) {
 
989
        el->appendChild(watchEl);
 
990
        }
 
991
        
 
992
        return;
 
993
}
 
994
 
 
995
void WatchRoot::restorePartialProjectSession(const QDomElement* el)
 
996
{
 
997
    QDomDocument domDoc = el->ownerDocument();
 
998
    if (domDoc.isNull()) {
 
999
        return;
 
1000
        }
 
1001
        
 
1002
    QDomElement watchEl = el->namedItem("watchExpressions").toElement();
 
1003
    QDomElement subEl = watchEl.firstChild().toElement();
 
1004
        
 
1005
    while (!subEl.isNull()) {
 
1006
                new WatchVarItem(this, subEl.firstChild().toText().data(), UNKNOWN_TYPE);
 
1007
                
 
1008
        subEl = subEl.nextSibling().toElement();
 
1009
    }
 
1010
        
 
1011
        return;
 
1012
}
 
1013
 
 
1014
// **************************************************************************
 
1015
// **************************************************************************
 
1016
// **************************************************************************
 
1017
 
 
1018
}
 
1019
 
 
1020
 
 
1021
#include "variablewidget.moc"
 
1022