#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "valgrind_part.h" #include "valgrind_widget.h" #define VALLISTVIEWITEMRTTI 130977 // helper class to sort the ListView by item number instead of the string representation of the item number class ValListViewItem: public TQListViewItem { public: ValListViewItem( TQListView* parent, int key, int pid, const TQString& message ): TQListViewItem( parent, TQString::number( key ), TQString::number( pid ), message ), _key( key ), _pid ( pid ), backtrace( false ), _line( -1 ), _active( false ) {} ValListViewItem( ValListViewItem* parent, int key, int pid, const TQString& message, const TQString& filename, int line, bool active ): TQListViewItem( parent, TQString::number( key ), TQString(), message ), _key( key ), _pid( pid ), backtrace( true ), _filename( filename ), _line( line ), _active( active ) { if ( parent->_pid != _pid && _pid > 0 ) setText( 1, TQString::number( _pid ) ); } virtual ~ValListViewItem(); static int intCompare( int i1, int i2 ) { if ( i1 > i2 ) return 1; else if ( i1 < i2 ) return -1; else return 0; } int compare( TQListViewItem* i, int col, bool ascending ) const { if ( !i || i->rtti() != VALLISTVIEWITEMRTTI ) return TQListViewItem::compare( i, col, ascending ); switch ( col ) { case 0 : return intCompare( ((ValListViewItem*)i)->_key, _key ); case 1 : return intCompare( ((ValListViewItem*)i)->_pid, _pid ); default: return TQListViewItem::compare( i, col, ascending ); } } void paintCell( TQPainter* p, const TQColorGroup& cg, int column, int width, int align ) { if ( _active ) { TQFont fnt = p->font(); fnt.setBold( true ); p->setFont( fnt ); } TQListViewItem::paintCell( p, cg, column, width, align ); } int rtti() const { return VALLISTVIEWITEMRTTI; } TQString fileName() const { return _filename; } int line() const { return _line; } TQString message() const { return text( 2 ); } bool isHighlighted() const { return _active; } private: int _key; int _pid; bool backtrace; TQString _filename; int _line; bool _active; }; ValListViewItem::~ValListViewItem() {} ValgrindWidget::ValgrindWidget( ValgrindPart *part ) : TQWidget(0, "valgrind widget"), _part( part ) { TQVBoxLayout* vbl = new TQVBoxLayout( this ); lv = new TDEListView( this ); lv->addColumn( i18n( "No." ) ); lv->addColumn( i18n( "Thread" ) ); lv->addColumn( i18n( "Message" ) ); lv->setSorting( 0, false ); lv->setRootIsDecorated( true ); lv->setAllColumnsShowFocus( true ); vbl->addWidget( lv ); popup = new TQPopupMenu( lv, "valPopup" ); popup->insertItem( i18n( "&Open Valgrind Output..." ), _part, TQT_SLOT(loadOutput()), 0, 0 ); popup->insertSeparator(); popup->insertItem( i18n( "Expand All Items" ), this, TQT_SLOT(expandAll()), 0, 2 ); popup->insertItem( i18n( "Collapse All Items" ), this, TQT_SLOT(collapseAll()), 0, 3 ); connect( popup, TQT_SIGNAL(aboutToShow()), this, TQT_SLOT(aboutToShowPopup()) ); connect( lv, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(executed(TQListViewItem*)) ); connect( lv, TQT_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQT_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&)) ); } ValgrindWidget::~ValgrindWidget() { } void ValgrindWidget::clear() { lv->clear(); msgNumber = 1; } void ValgrindWidget::addMessage( const ValgrindItem& vi ) { TQStringList projectFiles; TQString projectDirectory; ValListViewItem* lvi = new ValListViewItem( lv, msgNumber++, vi.pid(), vi.message() ); lvi->setMultiLinesEnabled( true ); const ValgrindItem::BacktraceList backtrace = vi.backtrace(); if ( !backtrace.isEmpty() ) lvi->setExpandable( true ); int i = 0; for ( ValgrindItem::BacktraceList::ConstIterator it = backtrace.begin(); it != backtrace.end(); ++it ) { new ValListViewItem( lvi, ++i, (*it).pid(), (*it).message(), (*it).url(), (*it).line(), (*it).isHighlighted() ); } } void ValgrindWidget::executed( TQListViewItem* lvi ) { Q_ASSERT( _part ); Q_ASSERT( _part->partController() ); Q_ASSERT( _part->mainWindow() ); if ( !lvi || lvi->rtti() != VALLISTVIEWITEMRTTI ) return; ValListViewItem* vli = 0; if ( !((ValListViewItem*)lvi)->fileName().isEmpty() ) { vli = (ValListViewItem*)lvi; } else if ( lvi->isExpandable() ) { // find the memleak position TQListViewItemIterator it( lv ); while ( vli == 0 && it.current() ) { if ( it.current()->rtti() == VALLISTVIEWITEMRTTI && ((ValListViewItem*)it.current())->isHighlighted() ) vli = (ValListViewItem*)it.current(); ++it; } } if ( vli ) { // display the file _part->partController()->editDocument( KURL( vli->fileName() ), vli->line() - 1 ); _part->mainWindow()->statusBar()->message( vli->message(), 10000 ); } } void ValgrindWidget::expandAll() { TQListViewItem* child = lv->firstChild(); while ( child ) { child->setOpen( true ); child = child->nextSibling(); } } void ValgrindWidget::collapseAll() { TQListViewItem* child = lv->firstChild(); while ( child ) { child->setOpen( false ); child = child->nextSibling(); } } void ValgrindWidget::aboutToShowPopup() { bool en = (lv->firstChild() != 0); popup->setItemEnabled( 2, en ); popup->setItemEnabled( 3, en ); } void ValgrindWidget::slotContextMenu( TDEListView* l, TQListViewItem* /*i*/, const TQPoint& p ) { if ( l != lv ) return; popup->exec( p ); } #include "valgrind_widget.moc"