From: <sv...@va...> - 2010-03-07 16:52:40
|
Author: cerion Date: 2010-03-07 16:52:32 +0000 (Sun, 07 Mar 2010) New Revision: 484 Log: Implemented support for on-demand loading of the logview items (VgOutputItems) from the underlying model (VgElements) Had to catch the treeView::itemExpanded() signal and pass it on to our implementation of QTreeWidgetItem (VgOutputItem). This code should be in VgOutputItem class, but QTreeWidgetItem no longer provides a virtual setExpanded() method :-( Still to do in memcheckview: openAll, showSrc, launchEditor. Modified: branches/valkyrie_qt4port/mainwindow.cpp branches/valkyrie_qt4port/toolview/memcheckview.cpp branches/valkyrie_qt4port/toolview/memcheckview.h branches/valkyrie_qt4port/toolview/vglogview.cpp branches/valkyrie_qt4port/toolview/vglogview.h branches/valkyrie_qt4port/utils/vglog.cpp Modified: branches/valkyrie_qt4port/mainwindow.cpp =================================================================== --- branches/valkyrie_qt4port/mainwindow.cpp 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/mainwindow.cpp 2010-03-07 16:52:32 UTC (rev 484) @@ -926,8 +926,9 @@ if ( vkConfig->value( "valkyrie/binary" ).toString().isEmpty() ) { vkInfo( this, "Run Valgrind: No program specified", - "Please specify (via Options->Valkyrie->Binary) the path to the program<br>" - "you wish to run, along with any arguments required" ); + "Please specify (via Options->Valkyrie->Binary)<br>" + "the path to the program you wish to run, along<br>" + "with any arguments required" ); openOptions(); return; Modified: branches/valkyrie_qt4port/toolview/memcheckview.cpp =================================================================== --- branches/valkyrie_qt4port/toolview/memcheckview.cpp 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/toolview/memcheckview.cpp 2010-03-07 16:52:32 UTC (rev 484) @@ -20,6 +20,7 @@ #include "toolview/memcheckview.h" #include "utils/vk_config.h" +#include "utils/vk_utils.h" #include <QAction> #include <QApplication> @@ -60,13 +61,23 @@ setupActions(); setupToolBar(); - /* enable | disable show*Item buttons */ + // enable | disable show*Item buttons connect( treeView, SIGNAL( itemSelectionChanged() ), - this, SLOT( itemSelected() ) ); - /* launch editor with src file loaded */ + this, SLOT( updateItemActions() ) ); + connect( treeView, SIGNAL( itemCollapsed( QTreeWidgetItem* ) ), + this, SLOT( itemCollapsed( QTreeWidgetItem* ) ) ); + connect( treeView, SIGNAL( itemExpanded( QTreeWidgetItem* ) ), + this, SLOT( updateItemActions() ) ); + + // load items on-demand + connect( treeView, SIGNAL( itemExpanded( QTreeWidgetItem* ) ), + this, SLOT( itemExpanded( QTreeWidgetItem* ) ) ); + + // launch editor with src file loaded connect( treeView, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( launchEditor( QTreeWidgetItem* ) ) ); - + + logview = new VgLogView( treeView ); } @@ -88,7 +99,7 @@ */ void MemcheckView::openLogFile() { - cerr << "MemcheckView::openLogFile()" << endl; +// cerr << "MemcheckView::openLogFile()" << endl; QString captn = "Select Log File"; QString filt = "XML Files (*.xml);;Log Files (*.log.*);;All Files (*)"; @@ -117,23 +128,8 @@ treeView = new QTreeWidget( this ); treeView->setObjectName( QString::fromUtf8( "treeMemcheck" ) ); treeView->setHeaderHidden( true ); + treeView->setRootIsDecorated( false ); vLayout->addWidget( treeView ); - - - // TODO: remove -#if 0 - // --- <test_setup> --- - treeView->setColumnCount( 1 ); - treeView->setRootIsDecorated( true ); - QTreeWidgetItem* item; - - for ( int i = 0; i < 10; ++i ) { - item = new QTreeWidgetItem( treeView, QStringList( QString( "memcheck: %1" ).arg( i ) ) ); - new QTreeWidgetItem( item, QStringList( QString( "boo! %1-1" ).arg( i ) ) ); - } - - // --- </test_setup> --- -#endif } @@ -153,7 +149,8 @@ icon_opencloseitem.addPixmap( QPixmap( QString::fromUtf8( ":/vk_icons/icons/item_close.png" ) ), QIcon::Normal, QIcon::On ); actMC_OpenClose_item->setIcon( icon_opencloseitem ); - connect( actMC_OpenClose_item, SIGNAL( triggered( bool ) ), this, SLOT( openOneItem( bool ) ) ); + connect( actMC_OpenClose_item, SIGNAL( triggered( bool ) ), + this, SLOT( openOneItem( bool ) ) ); actMC_OpenClose_all = new QAction( this ); actMC_OpenClose_all->setObjectName( QString::fromUtf8( "actMC_OpenClose_all" ) ); @@ -264,7 +261,7 @@ unsetCursor(); // ... turn on again only if they can be used - bool tree_empty = ( treeView->children().count() == 0 ); + bool tree_empty = ( treeView->topLevelItemCount() == 0 ); actMC_OpenClose_item->setEnabled( false ); // can't enable before item clicked actMC_OpenClose_item->setChecked( false ); // - and default to 'open' actMC_OpenClose_all->setEnabled( !tree_empty ); // enable only if sthng in tree @@ -290,20 +287,35 @@ { cerr << "MemcheckView::launchEditor( QTreeWidgetItem* ): " << code_item->text( 0 ).toLatin1().data() << endl; + cerr << "TODO" << endl; //TODO } /*! + Shows/Hides the file paths for all frames under current item. +*/ +void MemcheckView::showSrcPath( bool show_src ) +{ + cerr << "MemcheckView::showSrcPath(): " << show_src << endl; + cerr << "TODO" << endl; + //TODO + + + actMC_ShowSrcPaths->setChecked( show_src ); +} + + +/*! Opens all error items, including their children. Ignores non-error items (status, preample, etc). */ void MemcheckView::openAllItems( bool open_all ) { cerr << "MemcheckView::openAllItems(): " << open_all << endl; + cerr << "TODO" << endl; //TODO - - + actMC_OpenClose_all->setChecked( open_all ); } @@ -316,32 +328,84 @@ */ void MemcheckView::openOneItem( bool open_item ) { - cerr << "MemcheckView::openOneItem(): " << open_item << endl; - //TODO - - - actMC_OpenClose_item->setChecked( open_item ); + QTreeWidgetItem* item = treeView->currentItem(); + if ( item == 0 ) + return; + + // action and item state should be in sync. + vk_assert( open_item != item->isExpanded() ); + + // this should be a slot. grr! + item->setExpanded( !item->isExpanded() ); } /*! - Shows/Hides the file paths for all frames under current item. + void MemcheckView::itemExpanded( QTreeWidgetItem* item ) + + Supports on-demand loading our VgOutputItems from our underlying model (VgElements) + Have to catch the treeView::itemExpanded() signal and pass it on to our + implementation of QTreeWidgetItem (VgOutputItem). + + This should be in VgOutputItem class, but QTreeWidgetItem no longer + provides a virtual setExpanded() method :-( */ -void MemcheckView::showSrcPath( bool show_src ) +void MemcheckView::itemExpanded( QTreeWidgetItem* item ) { - cerr << "MemcheckView::showSrcPath(): " << show_src << endl; - //TODO - - - actMC_ShowSrcPaths->setChecked( show_src ); +// cerr << "MemcheckView::itemExpanded(): " << endl; + ((VgOutputItem*)item)->setupChildren(); } /*! - Updates actions (e.g. show-source) dependent on current selected item. + if we collapse a branch, set current item to branch head, + and update actions for selected item */ -void MemcheckView::itemSelected() +void MemcheckView::itemCollapsed( QTreeWidgetItem* item ) { - cerr << "MemcheckView::itemSelected()" << endl; - //TODO +// cerr << "MemcheckView::itemCollapsed(): " << endl; + + if ( item != treeView->currentItem() ) { + // this should be a slot. grr! + treeView->setCurrentItem( item ); + // item now changed: updateItemActions() will be called by signal + } else { + // item remained the same: updateItemActions() by hand. + updateItemActions(); + } } + + +/*! + Updates actions dependent on currently selected item. +*/ +void MemcheckView::updateItemActions() +{ +// cerr << "MemcheckView::updateItemActions(): " << endl; + + QTreeWidgetItem* item = treeView->currentItem(); + if ( !item ) { + actMC_OpenClose_item->setEnabled( false ); + } + else { + // item ok: contract / expand it + actMC_OpenClose_item->setEnabled( true ); + + if ( item->isExpanded() ) { + // set action to 'collapse' + actMC_OpenClose_item->setChecked( true ); + } + else { + // not expanded: is it expandable? + if ( ((VgOutputItem*)item)->getIsExpandable() ) { + // set action to 'expand' + actMC_OpenClose_item->setChecked( false ); + } else { + // not expanded, and not expandable -> disable action + actMC_OpenClose_item->setEnabled( false ); + + //TODO: for leaves, default to closing parent item? + } + } + } +} Modified: branches/valkyrie_qt4port/toolview/memcheckview.h =================================================================== --- branches/valkyrie_qt4port/toolview/memcheckview.h 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/toolview/memcheckview.h 2010-03-07 16:52:32 UTC (rev 484) @@ -70,8 +70,10 @@ void openOneItem( bool open_item ); void showSrcPath( bool show_src ); void launchEditor( QTreeWidgetItem* item ); - void itemSelected(); - + void itemExpanded( QTreeWidgetItem* item ); + void itemCollapsed( QTreeWidgetItem* item ); + void updateItemActions(); + signals: void saveLogFile(); Modified: branches/valkyrie_qt4port/toolview/vglogview.cpp =================================================================== --- branches/valkyrie_qt4port/toolview/vglogview.cpp 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/toolview/vglogview.cpp 2010-03-07 16:52:32 UTC (rev 484) @@ -82,6 +82,7 @@ void VgOutputItem::initialise() { isReadable = isWriteable = false; + isExpandable = false; } void VgOutputItem::setText( QString str ) @@ -121,9 +122,32 @@ #endif } -void VgOutputItem::setOpen( bool open ) +/*! + Setup children of this item. + Derived items use this to load children from the model on demand. + Rem to call this base class version at the end of derived methods, + in order to finish initialisation of children. + + Ideally, we'd have overloaded QWidgetTreeItem::setExpanded(), + but it's no longer virtual in Qt4 :-( +*/ +void VgOutputItem::setupChildren() { - QTreeWidgetItem::setExpanded( open ); +// cerr << "VgOutputItem::setupChildren()" << endl; + + // Top-level item: no init needed. + if ( parent() == 0 ) { + return; + } + + // now we've loaded any child items from the model, + // we can open up any child items that themselves have children + for ( int i=0; i<this->childCount(); ++i ) { + QTreeWidgetItem* chld = this->child( i ); + if ( chld->childCount() > 0 ) { + chld->setExpanded( true ); + } + } } @@ -158,9 +182,8 @@ .arg( num_blocks ); setText( status_str + "\n" + err_str ); - - //TODO: - // setMultiLinesEnabled( true ); + + isExpandable = true; } // finished @@ -400,39 +423,36 @@ setText( content ); - //TODO - // setExpandable( true ); + isExpandable = true; } -void InfoItem::setOpen( bool open ) +void InfoItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* after = 0; // handle any number of log-file-qualifiers VgElement logqual = elem.getFirstElem( "logfilequalifier" ); - while ( !logqual.isNull() && logqual.tagName() == "logfilequalifier" ) { after = new LogQualItem( this, logqual ); - after->setOpen( true ); + after->setupChildren(); logqual = logqual.getNextSibling(); } + // may / may not have a user comment VgElement comment = elem.getFirstElem( "usercomment" ); - - // may / may not have a user comment if ( ! comment.isNull() ) { after = new CommentItem( this, after, comment ); - after->setOpen( true ); + after->setupChildren(); } + // args VgElement args = elem.getFirstElem( "args" ); - // args after = new ArgsItem( this, after, args ); - after->setOpen( true ); + after->setupChildren(); + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -445,11 +465,13 @@ : VgOutputItem( parent, logqual ) { setText( "logfilequalifier" ); + + isExpandable = true; } -void LogQualItem::setOpen( bool open ) +void LogQualItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* last_item = 0; QDomElement e = elem.firstChild().toElement(); @@ -458,11 +480,9 @@ last_item = new VgOutputItem( this, last_item, elem ); last_item->setText( elem.text() ); } + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); - //TODO - // setExpandable( true ); } @@ -478,16 +498,14 @@ setText( "usercomment" ); } -void CommentItem::setOpen( bool open ) +void CommentItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* item = new VgOutputItem( this, elem ); item->setText( elem.text() ); } - - VgOutputItem::setOpen( open ); - //TODO - // setExpandable( true ); + + VgOutputItem::setupChildren(); } @@ -501,13 +519,12 @@ : VgOutputItem( parent, after, args ) { setText( "args" ); - //TODO - // setExpandable( true ); + isExpandable = true; } -void ArgsItem::setOpen( bool open ) +void ArgsItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgElement vgInfo = elem.getFirstElem( "vargv" ); VgElement exInfo = elem.getFirstElem( "argv" ); @@ -527,9 +544,9 @@ last_item = new VgOutputItem( this, last_item, elem ); last_item->setText( e.text() ); } + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -545,13 +562,13 @@ VgPreamble preamble ) : VgOutputItem( parent, after, preamble ) { - //TODO - // setExpandable( true ); setText( "Preamble" ); + isExpandable = true; } -void PreambleItem::setOpen( bool open ) + +void PreambleItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* last_item = 0; QDomElement e = elem.firstChild().toElement(); @@ -560,9 +577,9 @@ last_item = new VgOutputItem( this, last_item, elem ); last_item->setText( e.text() ); } + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -594,9 +611,8 @@ else { setText( err_tmplt.arg( acnym ).arg( 1 ).arg( what ) ); } - - //TODO - // setExpandable( true ); + + isExpandable = true; } void ErrorItem::updateCount( QString count ) @@ -609,15 +625,15 @@ } } -void ErrorItem::setOpen( bool open ) +void ErrorItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* after = this; // main stack VgElement main_stack = elem.getFirstElem( "stack" ); VgOutputItem* stack_item1 = new StackItem( this, after, main_stack ); - stack_item1->setOpen( true ); + stack_item1->setupChildren(); after = stack_item1; // aux what & stack @@ -633,7 +649,7 @@ VgElement auxstack = ( VgElement& )aux_stack; StackItem* si = new StackItem( this, after, auxstack ); after = si; - si->setOpen( true ); + si->setupChildren(); } } @@ -649,17 +665,17 @@ after = ori_item; StackItem* si = new StackItem( this, after, ori_stack ); - si->setOpen( true ); + si->setupChildren(); } + VgOutputItem::setupChildren(); + /* We should really check that we've used up all the children at this level. But that's difficult since we don't scan through them from one end to another using any 'cursor' kind of arrangement, so we can't easily check that the 'cursor' is at the last sibling. */ } - - VgOutputItem::setOpen( open ); } /*! @@ -687,24 +703,27 @@ : VgOutputItem( parent, after, stck ) { setText( "stack" ); - //TODO - // setExpandable( true ); + + isExpandable = true; } -void StackItem::setOpen( bool open ) +void StackItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* after = this; QDomElement e = elem.firstChild().toElement(); for ( ; !e.isNull(); e = e.nextSibling().toElement() ) { VgFrame frame = ( VgFrame& )e; after = new FrameItem( this, after, frame ); - after->setOpen( false ); + +// TODO: false?! +// after->setupChildren( false ); +// after->setupChildren(); } + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -739,13 +758,17 @@ } setText( frm.describe_IP() ); - //TODO - // setExpandable( isReadable || isWriteable ); + + isExpandable = ( isReadable || isWriteable ); } -void FrameItem::setOpen( bool open ) + +void FrameItem::setupChildren() { - if ( open && childCount() == 0 && isReadable ) { +// TODO: isReadable correct here? +// isExpandable ? + + if ( childCount() == 0 && isReadable ) { QDomElement srcdir = elem.getFirstElem( "dir" ); QDomElement srcfile = elem.getFirstElem( "file" ); QDomElement line = elem.getFirstElem( "line" ); @@ -770,10 +793,11 @@ // create the item for the src lines SrcItem* src_item = new SrcItem( this, srcline, path ); - src_item->setOpen( true ); + src_item->setupChildren(); + + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -854,8 +878,6 @@ } setText( src_lines ); - //TODO - // setMultiLinesEnabled( true ); } SrcItem::~SrcItem() @@ -909,13 +931,13 @@ : VgOutputItem( parent, after, sc ) { setText( "Suppressed errors" ); - //TODO: - // setExpandable( true ); + + isExpandable = true; } -void SuppCountsItem::setOpen( bool open ) +void SuppCountsItem::setupChildren() { - if ( open && childCount() == 0 ) { + if ( childCount() == 0 ) { VgOutputItem* child_item = 0; QDomNodeList pairs = elem.childNodes(); QDomElement e = pairs.item( 0 ).toElement(); @@ -929,9 +951,9 @@ child_item = new VgOutputItem( this, child_item, pair ); child_item->setText( supp_str ); } + + VgOutputItem::setupChildren(); } - - VgOutputItem::setOpen( open ); } @@ -960,9 +982,10 @@ QDomElement e = node.toElement(); VgElement elem = ( VgElement& )e; - - // populate listview - + + // populate listview with top-level items, from our model (VgElements) + // children of these items are only populated on-demand + switch ( elem.elemType() ) { case VgElement::STATUS: { VgStatus status = ( VgStatus& )elem; @@ -972,8 +995,11 @@ VgElement exe = args().getFirstElem( "argv" ).getFirstElem( "exe" ); topStatus = new TopStatusItem( view, status, exe, protocol().text() ); - topStatus->setOpen( true ); + topStatus->setExpanded( true ); + lastChild = new InfoItem( topStatus, docroot() ); + lastChild->setChildIndicatorPolicy( QTreeWidgetItem::ShowIndicator ); + lastChild = new PreambleItem( topStatus, lastChild, preamble() ); } else { @@ -986,7 +1012,7 @@ case VgElement::ERROR: { VgError err = ( VgError& )elem; lastChild = new ErrorItem( topStatus, lastChild, err ); - + if ( err.isLeak() ) { // update topStatus topStatus->updateLeakCounts( err ); @@ -1016,7 +1042,11 @@ default: break; } - + + if ( lastChild ) { + lastChild->setChildIndicatorPolicy( QTreeWidgetItem::ShowIndicator ); + } + return true; } Modified: branches/valkyrie_qt4port/toolview/vglogview.h =================================================================== --- branches/valkyrie_qt4port/toolview/vglogview.h 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/toolview/vglogview.h 2010-03-07 16:52:32 UTC (rev 484) @@ -33,8 +33,8 @@ // ============================================================ /* VgOutputItem: base class - item classes set up their own state and text in their construtors, - and item->setOpen() sets up item's children. + item classes set up their own state and text in their constructors, + and item->setupChildren() sets up item's children. - only spends time populating an item when made visible - no item opened before setup (inc. children's) finished. only a couple of sub-classes currently implement different @@ -56,13 +56,19 @@ VgOutputItem* parent(); void paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ); - void setOpen( bool open ); + virtual void setupChildren(); + + // since we add children on demand, we can't use childCount() + virtual bool getIsExpandable() { + return isExpandable; + } VgElement::ElemType elemType() { return elem.elemType(); } public: + bool isExpandable; bool isReadable, isWriteable; VgElement elem; // associated element }; @@ -92,7 +98,7 @@ { public: InfoItem( VgOutputItem* parent, VgElement root ); - void setOpen( bool open ); + void setupChildren(); }; @@ -101,7 +107,7 @@ { public: LogQualItem( VgOutputItem* parent, VgElement logqual ); - void setOpen( bool open ); + void setupChildren(); }; @@ -111,7 +117,7 @@ public: CommentItem( VgOutputItem* parent, QTreeWidgetItem* after, VgElement cmnt ); - void setOpen( bool open ); + void setupChildren(); }; @@ -121,7 +127,7 @@ public: ArgsItem( VgOutputItem* parent, QTreeWidgetItem* after, VgElement vgargs ); - void setOpen( bool open ); + void setupChildren(); }; @@ -131,7 +137,7 @@ public: PreambleItem( VgOutputItem* parent, QTreeWidgetItem* after, VgPreamble preamble ); - void setOpen( bool open ); + void setupChildren(); }; @@ -141,7 +147,7 @@ public: ErrorItem( VgOutputItem* parent, QTreeWidgetItem* after, VgError err ); - void setOpen( bool open ); + void setupChildren(); void updateCount( QString count ); bool isLeak() { return (( VgError* )&elem )->isLeak(); @@ -163,7 +169,7 @@ public: StackItem( VgOutputItem* parent, QTreeWidgetItem* after, VgElement stck ); - void setOpen( bool open ); + void setupChildren(); }; @@ -173,7 +179,7 @@ public: FrameItem( VgOutputItem* parent, QTreeWidgetItem* after, VgFrame frm ); - void setOpen( bool open ); + void setupChildren(); }; @@ -206,7 +212,7 @@ public: SuppCountsItem( VgOutputItem* parent, QTreeWidgetItem* after, VgSuppCounts sc ); - void setOpen( bool open ); + void setupChildren(); }; Modified: branches/valkyrie_qt4port/utils/vglog.cpp =================================================================== --- branches/valkyrie_qt4port/utils/vglog.cpp 2010-03-07 14:52:00 UTC (rev 483) +++ branches/valkyrie_qt4port/utils/vglog.cpp 2010-03-07 16:52:32 UTC (rev 484) @@ -697,8 +697,8 @@ vkPrintErr( "VgLog::appendNode(): bad xml protocol version" ); return false; } - break; + case VgElement::PREAMBLE: case VgElement::PID: case VgElement::PPID: @@ -711,6 +711,7 @@ case VgElement::ERRORCOUNTS: case VgElement::SUPPCOUNTS: break; + default: vkPrintErr( "VgLog::appendNode(): not a top-level tagname: %s", qPrintable( elem.tagName() ) ); |