diff options
Diffstat (limited to 'languages/ruby/debugger/variablewidget.cpp')
-rw-r--r-- | languages/ruby/debugger/variablewidget.cpp | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/languages/ruby/debugger/variablewidget.cpp b/languages/ruby/debugger/variablewidget.cpp new file mode 100644 index 00000000..0dbdce9a --- /dev/null +++ b/languages/ruby/debugger/variablewidget.cpp @@ -0,0 +1,1018 @@ +// ************************************************************************** +// begin : Sun Aug 8 1999 +// copyright : (C) 1999 by John Birch +// email : [email protected] +// +// Adapted for ruby debugging +// -------------------------- +// begin : Mon Nov 1 2004 +// copyright : (C) 2004 by Richard Dale +// email : [email protected] +// ************************************************************************** + +// ************************************************************************** +// * * +// * This program is free software; you can redistribute it and/or modify * +// * it under the terms of the GNU General Public License as published by * +// * the Free Software Foundation; either version 2 of the License, or * +// * (at your option) any later version. * +// * * +// ************************************************************************** + +#include "variablewidget.h" +#include "rdbparser.h" +#include "rdbcommand.h" + +#include <kdebug.h> +#include <kpopupmenu.h> +#include <klineedit.h> +#include <kdeversion.h> + +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qhbox.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qcursor.h> +#include <klocale.h> + +#include <qpoint.h> +#include <qclipboard.h> +#include <kapplication.h> + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +namespace RDBDebugger +{ + +VariableWidget::VariableWidget(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + varTree_ = new VariableTree(this); + QLabel *label = new QLabel(i18n("E&xpression to watch:"), this); + + QHBox *watchEntry = new QHBox( this ); + watchVarEditor_ = new KHistoryCombo( watchEntry, "var-to-watch editor"); + label->setBuddy(watchVarEditor_); + + QPushButton *addButton = new QPushButton(i18n("&Add"), watchEntry ); + addButton->adjustSize(); + addButton->setFixedWidth(addButton->width()); + + QBoxLayout * vbox = new QVBoxLayout(); + vbox->addWidget( label ); + vbox->addWidget( watchEntry ); + + QVBoxLayout *topLayout = new QVBoxLayout(this, 2); + topLayout->addWidget(varTree_, 10); + topLayout->addLayout( vbox ); + + connect( addButton, SIGNAL(clicked()), SLOT(slotAddWatchExpression()) ); + connect( watchVarEditor_, SIGNAL(returnPressed()), SLOT(slotAddWatchExpression()) ); +} + + +// ************************************************************************** + +void VariableWidget::setEnabled(bool bEnabled) +{ + QWidget::setEnabled(bEnabled); + if (bEnabled && parentWidget() != 0) { + varTree_->setColumnWidth(0, parentWidget()->width()/2); + } +} +// ************************************************************************** + +void VariableWidget::slotAddWatchExpression() +{ + QString watchVar(watchVarEditor_->currentText()); + if (!watchVar.isEmpty()) { + slotAddWatchExpression(watchVar); + } +} + +// ************************************************************************** + +void VariableWidget::slotAddWatchExpression(const QString &ident) +{ + if (!ident.isEmpty()) { + watchVarEditor_->addToHistory(ident); + varTree_->slotAddWatchExpression(ident); + watchVarEditor_->clearEdit(); + } +} + +// ************************************************************************** + +void VariableWidget::focusInEvent(QFocusEvent */*e*/) +{ + varTree_->setFocus(); +} + +void VariableWidget::restorePartialProjectSession(const QDomElement* el) +{ + varTree_->watchRoot()->restorePartialProjectSession(el); +} + +void VariableWidget::savePartialProjectSession(QDomElement* el) +{ + varTree_->watchRoot()->savePartialProjectSession(el); +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +VariableTree::VariableTree(VariableWidget *parent, const char *name) + : KListView(parent, name), + QToolTip( viewport() ), + activationId_(0), + currentThread_(-1), + selectedFrame_(0), + watchRoot_(0), + globalRoot_(0) +{ + setRootIsDecorated(true); + setAllColumnsShowFocus(true); + setColumnWidthMode(0, Manual); + setSorting(VAR_NAME_COLUMN); + QListView::setSelectionMode(QListView::Single); + + addColumn(i18n("Variable"), 100 ); + addColumn(i18n("Value"), 100 ); + + connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), + SLOT(slotContextMenu(KListView*, QListViewItem*)) ); + + connect( this, SIGNAL(pressed(QListViewItem*)), + this, SLOT(slotPressed(QListViewItem*)) ); + + watchRoot_ = new WatchRoot(this); +} + +// ************************************************************************** + +VariableTree::~VariableTree() +{ +} + +// ************************************************************************** + +void VariableTree::clear() +{ + QListViewItem *sibling = firstChild(); + while (sibling != 0) { + QListViewItem * current = sibling; + sibling = sibling->nextSibling(); + if (current->rtti() != RTTI_WATCH_ROOT) { + delete current; + } + } + + globalRoot_ = 0; + selectedFrame_ = 0; + return; +} + +// ************************************************************************** + +void VariableTree::slotContextMenu(KListView *, QListViewItem *item) +{ + if (item == 0) + return; + + setSelected(item, true); // Need to select this item. + + if (item->parent() != 0) { + KPopupMenu popup(this); + popup.insertTitle(item->text(VAR_NAME_COLUMN)); + int idRemoveWatch = -2; + if (item->rtti() == RTTI_WATCH_VAR_ITEM) { + idRemoveWatch = popup.insertItem( i18n("Remove Watch Expression") ); + } + + int idCopyToClipboard = popup.insertItem( i18n("Copy to Clipboard") ); + int res = popup.exec(QCursor::pos()); + + if (res == idRemoveWatch) { + emit removeWatchExpression(((WatchVarItem*)item)->displayId()); + delete item; + } else if (res == idCopyToClipboard) { + QClipboard *qb = KApplication::clipboard(); + QString text = "{ \"" + item->text( VAR_NAME_COLUMN ) + "\", " + + "\"" + item->text( VALUE_COLUMN ) + "\" }"; + + qb->setText( text, QClipboard::Clipboard ); + } + } +} + +/***************************************************************************/ + +void VariableTree::setSelected(QListViewItem * item, bool selected) +{ + // Save the last selected VarFrameRoot for slotPressed() to restore + if (item->rtti() == RTTI_VAR_FRAME_ROOT && selected) { + selectedFrame_ = (VarFrameRoot *) item; + } + + QListView::setSelected(item, selected); +} + +/***************************************************************************/ + +// Makes sure that only VarFrameRoot items can be selected +void VariableTree::slotPressed(QListViewItem * item) +{ + if (item == 0) { + return; + } + + while (item->rtti() == RTTI_VAR_ITEM) { + item = item->parent(); + } + + if ( item->rtti() == RTTI_GLOBAL_ROOT + || item->rtti() == RTTI_WATCH_ROOT + || item->rtti() == RTTI_WATCH_VAR_ITEM ) + { + if (selectedFrame_ != 0) { + setSelected(selectedFrame_, true); + } + return; + } + + if (item->rtti() == RTTI_VAR_FRAME_ROOT) { + VarFrameRoot * frame = (VarFrameRoot*) item; + emit selectFrame(frame->frameNo(), frame->threadNo()); + } + + return; +} + +// ************************************************************************** + +void VariableTree::prune() +{ + QListViewItem *child = firstChild(); + + while (child != 0) { + QListViewItem *nextChild = child->nextSibling(); + + // Only prune var frames, not the watch or global root + if (child->rtti() == RTTI_VAR_FRAME_ROOT) { + if (((VarFrameRoot*) child)->isActive()) { + if (child->isOpen()) { + ((VarFrameRoot*) child)->prune(); + } + } else { + delete child; + } + } + + child = nextChild; + } +} + +// ************************************************************************** + +// The debugger has moved onto the next program pause, so invalidate +// everything in the Variable Tree +void VariableTree::nextActivationId() +{ + activationId_++; + globalRoot()->setActivationId(); + watchRoot()->setActivationId(); + // ..but that's only the Watch and Global roots +} + +// ************************************************************************** + +// VarFrameRoot frames in the Variable Tree from the previous program pause, +// are set active here. Notified by the Frame Stack widget when it parses the +// backtrace from the 'where' command after a pause. +// +// After that, any frames which aren't marked as active must have gone +// out of scope and will end up pruned. +void VariableTree::slotFrameActive(int frameNo, int threadNo, const QString& frameName) +{ + VarFrameRoot * frame = findFrame(frameNo, threadNo); + if (frameNo == 1) { + // If the current frame 1 doesn't exist, create it + if (frame == 0) { + frame = new VarFrameRoot(this, frameNo, threadNo); + } + + frame->setFrameName(frameName); + } + + if (frame != 0 && frame->text(VAR_NAME_COLUMN) == frameName) { + frame->setActivationId(); + } +} + +// ************************************************************************** + +bool VariableTree::schedule() +{ + QListViewItem * child = firstChild(); + VarFrameRoot * frame = 0; + + while (child != 0) { + if (child->rtti() == RTTI_VAR_FRAME_ROOT) { + frame = (VarFrameRoot *) child; + Q_ASSERT( !frame->isWaitingForData() ); + + if (frame->needsVariables()) { + if (QApplication::overrideCursor() == 0) { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + } + + // Tell the controller to fetch the variable values + emit selectFrame(frame->frameNo(), frame->threadNo()); + return true; + } + } + + child = child->nextSibling(); + } + + frame = findFrame(1, currentThread_); + Q_ASSERT( frame != 0 ); + Q_ASSERT( !frame->needsVariables() ); + + // All over, nothing left to fetch. + // Return to frame 1, and prune the inactive items + // from the variable tree.. + QApplication::restoreOverrideCursor(); + emit selectFrame(1, currentThread_); + prune(); + + return false; +} + +// ************************************************************************** + +void VariableTree::slotAddWatchExpression(const QString &watchVar) +{ + new WatchVarItem(watchRoot(), watchVar, UNKNOWN_TYPE); + emit addWatchExpression(watchVar, true); +} + + +// ************************************************************************** + +void VariableTree::setFetchGlobals(bool fetch) +{ + emit fetchGlobals(fetch); +} + +// ************************************************************************** + +VarFrameRoot *VariableTree::findFrame(int frameNo, int threadNo) const +{ + // frames only exist on the top level so we only need to + // check the siblings + QListViewItem *sibling = firstChild(); + while (sibling != 0) { + if ( sibling->rtti() == RTTI_VAR_FRAME_ROOT + && ((VarFrameRoot*) sibling)->frameNo() == frameNo + && ((VarFrameRoot*) sibling)->threadNo() == threadNo ) + { + return (VarFrameRoot*) sibling; + } + + sibling = sibling->nextSibling(); + } + + return 0; +} + +// ************************************************************************** + +WatchRoot *VariableTree::watchRoot() +{ + return watchRoot_; +} + +// ************************************************************************** + +GlobalRoot *VariableTree::globalRoot() +{ + if (globalRoot_ == 0) { + globalRoot_ = new GlobalRoot(this); + } + + return globalRoot_; +} + +// ************************************************************************** + +// Watch variables can be added before the start of a debugging session, +// so tell the controller about any already in the tree at start. +void VariableTree::resetWatchVars() +{ + for (QListViewItem *child = watchRoot()->firstChild(); child != 0; child = child->nextSibling()) { + ((WatchVarItem*) child)->setDisplayId(-1); + emit addWatchExpression(child->text(VAR_NAME_COLUMN), false); + } +} + +// ************************************************************************** + +void VariableTree::maybeTip(const QPoint &p) +{ + VarItem * item = dynamic_cast<VarItem*>( itemAt(p) ); + if (item != 0) { + QRect r = itemRect(item); + if (r.isValid()) { + tip(r, item->tipText()); + } + } +} + + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +LazyFetchItem::LazyFetchItem(VariableTree *parent) + : KListViewItem(parent), + activationId_(0), + waitingForData_(false) +{ + setActivationId(); +} + +// ************************************************************************** + +LazyFetchItem::LazyFetchItem(LazyFetchItem *parent) + : KListViewItem(parent), + activationId_(0), + waitingForData_(false) +{ + setActivationId(); +} + +// ************************************************************************** + +LazyFetchItem::~LazyFetchItem() +{ +} + +// ************************************************************************** + +void LazyFetchItem::paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int align) +{ + if (p == 0) { + return; + } + + // make toplevel item (watch and frame items) names bold + if (column == VAR_NAME_COLUMN && parent() == 0) { + QFont f = p->font(); + f.setBold(true); + p->setFont(f); + } + + QListViewItem::paintCell( p, cg, column, width, align ); +} + +// ************************************************************************** + +VarItem *LazyFetchItem::findItem(const QString &name) const +{ + QListViewItem *child = firstChild(); + + // Check the siblings on this branch + while (child != 0) { + if (child->text(VAR_NAME_COLUMN) == name) { + return (VarItem*) child; + } + + child = child->nextSibling(); + } + + return 0; +} + +// ************************************************************************** + +void LazyFetchItem::prune() +{ + QListViewItem *child = firstChild(); + + while (child != 0) { + LazyFetchItem *item = (LazyFetchItem*) child; + child = child->nextSibling(); + // Never prune a branch if we are waiting on data to arrive. + if (!waitingForData_) { + if (item->isActive()) { + item->prune(); + } else { + delete item; + } + } + } +} + + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +VarItem::VarItem(LazyFetchItem *parent, const QString &varName, DataType dataType) + : LazyFetchItem (parent), + cache_(QCString()), + dataType_(dataType), + highlight_(false) +{ + setText(VAR_NAME_COLUMN, varName); + setSelectable(false); + + // Order the VarItems so that globals are first, then + // constants, class variables, instance variables and + // finally local variables + + // Matches either an array element or a string slice, + // Order on the array index or the first number in the + // range specifying the slice. + QRegExp arrayelement_re("\\[(\\d+)(\\.\\.\\d+)?\\]"); + key_ = varName; + + if (arrayelement_re.search(varName) != -1) { + key_.sprintf("%.6d", arrayelement_re.cap(1).toInt()); + } else if (key_.startsWith("$")) { + key_.prepend("1001"); // Global variable + } else if (QRegExp("^[A-Z]").search(varName) != -1) { + key_.prepend("1002"); // Constant + } else if (key_.startsWith("@@")) { + key_.prepend("1003"); // Class variable + } else if (key_.startsWith("@")) { + key_.prepend("1004"); // Instance variable + } else { + key_.prepend("1005"); // Local variable or parameter + } + +// kdDebug(9012) << " ### VarItem::VarItem *CONSTR* " << varName << endl; +} + +// ************************************************************************** + +VarItem::~VarItem() +{ +} + +QString VarItem::key(int /*column*/, bool /*ascending*/) const +{ + return key_; +} + +// ************************************************************************** + +// Returns the path of a ruby item. If it is an instance variable, assume +// that there is an attr_accessor method for it. +// For example, @foobar within instance obj is accessed as obj.foobar. +// But don't strip off the @ for an instance variable with no path, +// and leave a plain '@foobar' as it is. +QString VarItem::fullName() const +{ + QString itemName = text(VAR_NAME_COLUMN); + QString vPath(""); + const VarItem *item = this; + + if (item->parent()->rtti() != RTTI_VAR_ITEM) { + return itemName; + } + + // This stops at the root item (FrameRoot or GlobalRoot) + while (item->rtti() == RTTI_VAR_ITEM) { + QString itemName = item->text(VAR_NAME_COLUMN); + + if (vPath.startsWith("[")) { + // If it's a Hash or an Array, then just insert the value. As + // in adding '[0]' to foo.bar to give foo.bar[0] + vPath.prepend(itemName); + } else { + if (vPath.isEmpty()) { + vPath = itemName; + } else { + vPath.prepend(itemName + "."); + } + } + item = (VarItem*) item->parent(); + } + + // Change 'self.@foobar' to '@foobar' + vPath.replace(QRegExp("^self\\.@"), "@"); + + // Use instance_variable_get() to access any '@var's in the middle of a path + QRegExp re_instance_var("\\.(@[^\\[.]+)"); + int pos = re_instance_var.search(vPath); + while (pos != -1) { + vPath.replace( pos, + re_instance_var.matchedLength(), + QString(".instance_variable_get(:") + re_instance_var.cap(1) + ")" ); + pos = re_instance_var.search(vPath, pos); + } + + return vPath; +} + +// ************************************************************************** + +void VarItem::setText(int column, const QString &data) +{ + setActivationId(); + + if (column == VALUE_COLUMN) { + highlight_ = (!text(VALUE_COLUMN).isEmpty() && text(VALUE_COLUMN) != data); + } + + QListViewItem::setText(column, data); + repaint(); +} + +// ************************************************************************** + +void VarItem::expandValue(char *buf) +{ + LazyFetchItem::stopWaitingForData(); + RDBParser::parseExpandedVariable(this, buf); +} + +// ************************************************************************** + +void VarItem::setOpen(bool open) +{ + QListViewItem::setOpen(open); + + Q_ASSERT( dataType_ == REFERENCE_TYPE + || dataType_ == ARRAY_TYPE + || dataType_ == HASH_TYPE + || dataType_ == STRING_TYPE + || dataType_ == STRUCT_TYPE ); + + update(); + return; +} + +// ************************************************************************** + +void VarItem::update() +{ + if (isOpen()) { + startWaitingForData(); +// emit ((VariableTree*)listView())->expandItem(this, fullName().latin1()); + ((VariableTree*)listView())->expandItem(this, fullName().latin1()); + } + + return; +} + +// ************************************************************************** + +DataType VarItem::dataType() const +{ + return dataType_; +} + +// ************************************************************************** + +void VarItem::setDataType(DataType dataType) +{ + dataType_ = dataType; +} + +// ************************************************************************** + +// Overridden to highlight the changed items +void VarItem::paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int align) +{ + if (p == 0) { + return; + } + + if (column == VALUE_COLUMN) { + // Show color values as colors, and make the text color the same + // as the base color + if (dataType_ == COLOR_TYPE) { + QRegExp color_re("\\s(#.*)>"); + + if (color_re.search(text(column)) != -1) { + QColorGroup color_cg( cg.foreground(), cg.background(), + cg.light(), cg.dark(), cg.mid(), + QColor(color_re.cap(1)), QColor(color_re.cap(1)) ); + QListViewItem::paintCell(p, color_cg, column, width, align); + return; + } + } + + // Highlight recently changed items in red + if (highlight_) { + QColorGroup hl_cg( cg.foreground(), cg.background(), + cg.light(), cg.dark(), cg.mid(), + red, cg.base() ); + QListViewItem::paintCell(p, hl_cg, column, width, align); + return; + } + } + + QListViewItem::paintCell(p, cg, column, width, align); + return; +} + +// ************************************************************************** + +QString VarItem::tipText() const +{ + const unsigned int MAX_TOOLTIP_SIZE = 70; + QString tip = text(VALUE_COLUMN); + + if (tip.length() < MAX_TOOLTIP_SIZE) { + return tip; + } else { + return tip.mid(0, MAX_TOOLTIP_SIZE - 1) + " [...]"; + } +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +VarFrameRoot::VarFrameRoot(VariableTree *parent, int frameNo, int threadNo) + : LazyFetchItem(parent), + needsVariables_(true), + frameNo_(frameNo), + threadNo_(threadNo), + cache_("") +{ + setExpandable(true); +} + +// ************************************************************************** + +VarFrameRoot::~VarFrameRoot() +{ +} + +// ************************************************************************** + +void VarFrameRoot::addLocals(char *variables) +{ + cache_.append(variables); +} + +// ************************************************************************** + +void VarFrameRoot::setLocals() +{ + RDBParser::parseVariables(this, cache_.data()); + cache_ = ""; + needsVariables_ = false; + stopWaitingForData(); + prune(); + + return; +} + +// ************************************************************************** + +// Override setOpen so that we can decide what to do when we do change +// state. +void VarFrameRoot::setOpen(bool open) +{ + bool localsViewChanged = (isOpen() != open); + QListViewItem::setOpen(open); + + if (localsViewChanged) { + ((VariableTree*)listView())->selectFrame(frameNo_, threadNo_); + } + + return; +} + +void VarFrameRoot::setFrameName(const QString &frameName) +{ + setText(VAR_NAME_COLUMN, frameName); + setText(VALUE_COLUMN, ""); + + return; +} + +void VarFrameRoot::setActivationId() +{ + LazyFetchItem::setActivationId(); + stopWaitingForData(); + needsVariables_ = true; + cache_ = ""; +} + +bool VarFrameRoot::needsVariables() const +{ + return ( text(VAR_NAME_COLUMN).contains("try_initialize") == 0 + && isOpen() + && !isWaitingForData() + && needsVariables_ ); +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + + +GlobalRoot::GlobalRoot(VariableTree *parent) + : LazyFetchItem(parent) +{ + setText(0, i18n("Global")); + setExpandable(true); + setOpen(false); + setSelectable(false); +} + +// ************************************************************************** + +GlobalRoot::~GlobalRoot() +{ +} + +// ************************************************************************** + +void GlobalRoot::setGlobals(char * globals) +{ + setActivationId(); + RDBParser::parseVariables(this, globals); + + return; +} + +// ************************************************************************** + +void GlobalRoot::setOpen(bool open) +{ + bool globalsViewChanged = (isOpen() != open); + QListViewItem::setOpen(open); + + if (globalsViewChanged) { + ((VariableTree*)listView())->setFetchGlobals(isOpen()); + } + + return; +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +WatchVarItem::WatchVarItem( LazyFetchItem *parent, const QString &varName, DataType dataType, int displayId ) + : VarItem(parent, varName, dataType), + displayId_(displayId) +{ +} + +// ************************************************************************** + +WatchVarItem::~WatchVarItem() +{ +} + +// ************************************************************************** + +void WatchVarItem::setDisplayId(int id) +{ + displayId_ = id; +} + +// ************************************************************************** + +int WatchVarItem::displayId() +{ + return displayId_; +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +WatchRoot::WatchRoot(VariableTree *parent) + : LazyFetchItem(parent) +{ + setText(VAR_NAME_COLUMN, i18n("Watch")); + setOpen(true); + setSelectable(false); +} + +// ************************************************************************** + +WatchRoot::~WatchRoot() +{ +} + +// ************************************************************************** + +// Sets the initial value of a new Watch item, along with the +// display id +void WatchRoot::setWatchExpression(char * buf, char * expression) +{ + QString expr(expression); + QRegExp display_re("^(\\d+):\\s([^\n]+)\n"); + + for ( QListViewItem *child = firstChild(); + child != 0; + child = child->nextSibling() ) + { + WatchVarItem *varItem = (WatchVarItem*) child; + if ( varItem->text(VAR_NAME_COLUMN) == expr + && varItem->displayId() == -1 + && display_re.search(buf) >= 0 ) + { + varItem->setDisplayId(display_re.cap(1).toInt()); + // Skip over the 'thing = ' part of expr to get the value + varItem->setText( VALUE_COLUMN, + display_re.cap(2).mid(varItem->text(VAR_NAME_COLUMN).length() + strlen(" = ")) ); + return; + } + } +} + +// After a program pause, this updates the new value of a Watch item +// expr is the thing = value part of "1: a = 1", id is the display number +void WatchRoot::updateWatchExpression(int id, const QString& expr) +{ + for ( QListViewItem *child = firstChild(); + child != 0; + child = child->nextSibling() ) + { + WatchVarItem *varItem = (WatchVarItem*) child; + if (varItem->displayId() == id) { + Q_ASSERT( expr.startsWith(varItem->text(VAR_NAME_COLUMN)) ); + // Skip over the 'thing = ' part of expr to get the value + varItem->setText( VALUE_COLUMN, + expr.mid(varItem->text(VAR_NAME_COLUMN).length() + strlen(" = ")) ); + return; + } + } +} + +void WatchRoot::savePartialProjectSession(QDomElement* el) +{ + QDomDocument domDoc = el->ownerDocument(); + if (domDoc.isNull()) { + return; + } + + QDomElement watchEl = domDoc.createElement("watchExpressions"); + + for ( QListViewItem *child = firstChild(); + child != 0; + child = child->nextSibling() ) + { + QDomElement subEl = domDoc.createElement("el"); + subEl.appendChild(domDoc.createTextNode(child->text(VAR_NAME_COLUMN))); + watchEl.appendChild(subEl); + } + + if (!watchEl.isNull()) { + el->appendChild(watchEl); + } + + return; +} + +void WatchRoot::restorePartialProjectSession(const QDomElement* el) +{ + QDomDocument domDoc = el->ownerDocument(); + if (domDoc.isNull()) { + return; + } + + QDomElement watchEl = el->namedItem("watchExpressions").toElement(); + QDomElement subEl = watchEl.firstChild().toElement(); + + while (!subEl.isNull()) { + new WatchVarItem(this, subEl.firstChild().toText().data(), UNKNOWN_TYPE); + + subEl = subEl.nextSibling().toElement(); + } + + return; +} + +// ************************************************************************** +// ************************************************************************** +// ************************************************************************** + +} + + +#include "variablewidget.moc" + |