diff options
Diffstat (limited to 'parts/valgrind/valgrind_widget.cpp')
-rw-r--r-- | parts/valgrind/valgrind_widget.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/parts/valgrind/valgrind_widget.cpp b/parts/valgrind/valgrind_widget.cpp new file mode 100644 index 00000000..356d97bf --- /dev/null +++ b/parts/valgrind/valgrind_widget.cpp @@ -0,0 +1,205 @@ +#include <qlayout.h> +#include <qpainter.h> +#include <qpopupmenu.h> + +#include <kparts/part.h> +#include <klibloader.h> +#include <kurl.h> +#include <kdebug.h> +#include <klistview.h> +#include <klocale.h> +#include <kstatusbar.h> + +#include <kdevcore.h> +#include <kdevpartcontroller.h> +#include <kdevmainwindow.h> +#include <kdevproject.h> + +#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 QListViewItem +{ +public: + ValListViewItem( QListView* parent, int key, int pid, const QString& message ): + QListViewItem( parent, QString::number( key ), QString::number( pid ), message ), + _key( key ), _pid ( pid ), backtrace( false ), _line( -1 ), _active( false ) {} + + ValListViewItem( ValListViewItem* parent, int key, int pid, const QString& message, const QString& filename, int line, bool active ): + QListViewItem( parent, QString::number( key ), QString::null, message ), + _key( key ), _pid( pid ), backtrace( true ), _filename( filename ), _line( line ), _active( active ) + { + if ( parent->_pid != _pid && _pid > 0 ) + setText( 1, QString::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( QListViewItem* i, int col, bool ascending ) const + { + if ( !i || i->rtti() != VALLISTVIEWITEMRTTI ) + return QListViewItem::compare( i, col, ascending ); + switch ( col ) { + case 0 : return intCompare( ((ValListViewItem*)i)->_key, _key ); + case 1 : return intCompare( ((ValListViewItem*)i)->_pid, _pid ); + default: return QListViewItem::compare( i, col, ascending ); + } + } + + void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int align ) + { + if ( _active ) { + QFont fnt = p->font(); + fnt.setBold( true ); + p->setFont( fnt ); + } + QListViewItem::paintCell( p, cg, column, width, align ); + } + + int rtti() const { return VALLISTVIEWITEMRTTI; } + + QString fileName() const { return _filename; } + int line() const { return _line; } + QString message() const { return text( 2 ); } + bool isHighlighted() const { return _active; } + +private: + int _key; + int _pid; + bool backtrace; + QString _filename; + int _line; + bool _active; +}; + +ValListViewItem::~ValListViewItem() {} + +ValgrindWidget::ValgrindWidget( ValgrindPart *part ) + : QWidget(0, "valgrind widget"), _part( part ) +{ + QVBoxLayout* vbl = new QVBoxLayout( this ); + lv = new KListView( 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 QPopupMenu( lv, "valPopup" ); + popup->insertItem( i18n( "&Open Valgrind Output..." ), _part, SLOT(loadOutput()), 0, 0 ); + popup->insertSeparator(); + popup->insertItem( i18n( "Expand All Items" ), this, SLOT(expandAll()), 0, 2 ); + popup->insertItem( i18n( "Collapse All Items" ), this, SLOT(collapseAll()), 0, 3 ); + + connect( popup, SIGNAL(aboutToShow()), + this, SLOT(aboutToShowPopup()) ); + connect( lv, SIGNAL(executed(QListViewItem*)), + this, SLOT(executed(QListViewItem*)) ); + connect( lv, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), + this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) ); +} + + +ValgrindWidget::~ValgrindWidget() +{ +} + +void ValgrindWidget::clear() +{ + lv->clear(); + msgNumber = 1; +} + +void ValgrindWidget::addMessage( const ValgrindItem& vi ) +{ + QStringList projectFiles; + QString 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( QListViewItem* 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 + QListViewItemIterator 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() +{ + QListViewItem* child = lv->firstChild(); + while ( child ) { + child->setOpen( true ); + child = child->nextSibling(); + } +} + +void ValgrindWidget::collapseAll() +{ + QListViewItem* 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( KListView* l, QListViewItem* /*i*/, const QPoint& p ) +{ + if ( l != lv ) + return; + + popup->exec( p ); +} + +#include "valgrind_widget.moc" |