#include <tqlayout.h>
#include <tqcheckbox.h>
#include <tqregexp.h>
#include <tqwidgetstack.h>

#include <kprocess.h>
#include <tdelocale.h>
#include <kurlrequester.h>
#include <klineedit.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>

#include "dialog_widget.h"
#include "valgrind_dialog.h"

#include "valgrind_dialog.moc"


ValgrindDialog::ValgrindDialog( Type type, TQWidget* parent )
  : KDialogBase( parent, "valgrind dialog", true, i18n("Valgrind Memory Check"), Ok|Cancel ),
  m_type(type)
{
  w = new DialogWidget( this );
  w->valExecutableEdit->setURL( "valgrind" );
  w->executableEdit->setFocus();
  w->stack->raiseWidget(m_type);
  setMainWidget( w );
  connect( w->executableEdit->lineEdit(),  TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( valgrindTextChanged()));
  connect( w->valExecutableEdit->lineEdit(), TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( valgrindTextChanged()));
  connect( w->ctExecutableEdit->lineEdit(),  TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( valgrindTextChanged()));
  connect( w->kcExecutableEdit->lineEdit(), TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( valgrindTextChanged()));
  enableButtonOK( false );
}


ValgrindDialog::~ValgrindDialog()
{
}

void ValgrindDialog::valgrindTextChanged()
{
    if (m_type == Memcheck)
        enableButtonOK( !w->valExecutableEdit->lineEdit()->text().isEmpty() &&  !w->executableEdit->lineEdit()->text().isEmpty() );
    else if (m_type == Calltree)
        enableButtonOK( !w->executableEdit->lineEdit()->text().isEmpty() &&  !w->ctExecutableEdit->lineEdit()->text().isEmpty() && !w->kcExecutableEdit->lineEdit()->text().isEmpty() );
}

TQString ValgrindDialog::executableName() const
{
  return w->executableEdit->url();
}

void ValgrindDialog::setExecutable( const TQString& url )
{
  w->executableEdit->setURL( url );
}

TQString ValgrindDialog::valExecutable() const
{
  return w->valExecutableEdit->url();
}

TQString ValgrindDialog::parameters() const
{
  return w->paramEdit->text();
}

void ValgrindDialog::setParameters( const TQString& params )
{
  w->paramEdit->setText( params );
}

void ValgrindDialog::setValExecutable( const TQString& ve )
{
  TQString vUrl = ve;
  if ( vUrl.isEmpty() ) {
    vUrl = TDEStandardDirs::findExe( "valgrind" );
  }
  if ( vUrl.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "Could not find valgrind in your $PATH. Please make "
                                    "sure it is installed properly." ),
                        i18n( "Valgrind Not Found" ) );
    w->valExecutableEdit->setURL( "valgrind" );
  } else {
    w->valExecutableEdit->setURL( vUrl );
  }
}

static const TQString memCheckParam( "--tool=memcheck" );
static const TQString leakCheckParam( "--leak-check=yes" );
static const TQString reachableParam( "--show-reachable=yes" );
static const TQString childrenParam( "--trace-children=yes" );

TQString ValgrindDialog::valParams() const
{
  TQString params = w->valParamEdit->text();
  if (isNewValgrindVersion())
    params += " " + memCheckParam;
  if ( w->memleakBox->isChecked() )
    params += " " + leakCheckParam;
  if ( w->reachableBox->isChecked() )
    params += " " + reachableParam;
  if ( w->childrenBox->isChecked() )
    params += " " + childrenParam;

  return params;
}

void ValgrindDialog::setValParams( const TQString& params )
{
  TQString myParams = params;
  if ( myParams.contains( leakCheckParam ) )
    w->memleakBox->setChecked( true );
  if ( myParams.contains( reachableParam ) )
    w->reachableBox->setChecked( true );
  if ( myParams.contains( childrenParam ) )
    w->childrenBox->setChecked( true );
  w->init();

  myParams = myParams.replace( TQRegExp( memCheckParam ), "" );
  myParams = myParams.replace( TQRegExp( leakCheckParam ), "" );
  myParams = myParams.replace( TQRegExp( reachableParam ), "" );
  myParams = myParams.replace( TQRegExp( childrenParam ), "" );
  myParams = myParams.stripWhiteSpace();
  w->valParamEdit->setText( myParams );
}

TQString ValgrindDialog::ctExecutable() const
{
  return w->ctExecutableEdit->url();
}

void ValgrindDialog::setCtExecutable( const TQString& ce )
{
  TQString vUrl = ce;
  if ( vUrl.isEmpty() ) {
    vUrl = TDEStandardDirs::findExe( "valgrind" );
  }
  if ( vUrl.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "Could not find valgrind in your $PATH. Please make "
                                    "sure it is installed properly." ),
                        i18n( "Valgrind Not Found" ) );
    w->ctExecutableEdit->setURL( "valgrind" );
  } else {
    w->ctExecutableEdit->setURL( vUrl );
  }
}

TQString ValgrindDialog::ctParams() const
{
  TQString params = w->ctParamEdit->text();
  if ( w->ctChildrenBox->isChecked() )
    params += " " + childrenParam;

  return params;
}

void ValgrindDialog::setCtParams( const TQString& params )
{
  TQString myParams = params;
  //force --tool=callgrind if no params are given
  if (myParams.isEmpty())
    myParams = "--tool=callgrind";
  if ( myParams.contains( childrenParam ) )
    w->ctChildrenBox->setChecked( true );
  w->init();

  myParams = myParams.replace( TQRegExp( childrenParam ), "" );
  myParams = myParams.stripWhiteSpace();
  w->ctParamEdit->setText( myParams );
}

TQString ValgrindDialog::kcExecutable( ) const
{
  return w->kcExecutableEdit->url();
}

void ValgrindDialog::setKcExecutable( const TQString& ke )
{
  TQString vUrl = ke;
  if ( vUrl.isEmpty() ) {
    vUrl = TDEStandardDirs::findExe( "tdecachegrind" );
  }
  if ( vUrl.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "Could not find tdecachegrind in your $PATH. Please make "
                                    "sure it is installed properly." ),
                        i18n( "KCachegrind Not Found" ) );
    w->kcExecutableEdit->setURL( "tdecachegrind" );
  } else {
    w->kcExecutableEdit->setURL( vUrl );
  }
}

bool ValgrindDialog::isNewValgrindVersion( ) const
{
  TDEProcess *proc = new TDEProcess;
  proc->setUseShell(true);
  *proc << "test \"valgrind-20\" == `valgrind --version | awk -F \\. '{print $1$2}'`";
  proc->start(TDEProcess::Block);
  if (proc->normalExit())
    return proc->exitStatus();
  return true;
}
