|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
|
|
|
|
#include <tdeparts/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 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"
|