/*****************************************************************
 * drkonki - The KDE Crash Handler
 * 
 * $Id: toplevel.cpp,v 1.26 2000/06/07 05:31:03 waba Exp $
 *
 * Copyright (C) 2000 Hans Petter Bieker <bieker@kde.org>
 *****************************************************************/

#include <qstring.h>
#include <qlabel.h>
#include <qhbox.h>

#include <klocale.h>
#include <kstddirs.h>
#include <kbugreport.h>
#include <kmessagebox.h>
#include <kprocess.h>

#include "backtrace.h"
#include "drbugreport.h"
#include "debugger.h"
#include "krashconf.h"
#include "toplevel.h"
#include "toplevel.moc"

Toplevel :: Toplevel(const KrashConfig *krashconf, QWidget *parent, const char *name)
  : KDialogBase( Tabbed,
		 krashconf->programName(),
                 User2 | User1 | Close,
                 Close,
                 parent,
                 name,
                 true, // modal
                 true, // separator
		 i18n("&Bug report"),
		 i18n("&Debugger")
		 ),
    m_krashconf(krashconf), bugreport(0)
{
  QHBox *page = addHBoxPage(i18n("General"));
  page->setSpacing(20);

  // picture of konqi
  QLabel *lab = new QLabel(page);
  lab->setBackgroundColor(Qt::white);
  lab->setFrameStyle(QFrame::Panel | QFrame::Raised);
  QPixmap pix(locate("appdata", QString::fromLatin1("pics/konqi.png")));
  lab->setPixmap(pix);

  new QLabel( generateText(), page );

  if (m_krashconf->showBacktrace()) {
    page = addHBoxPage(i18n("Backtrace"));
    new KrashDebugger(m_krashconf, page);
  }

  showButton( User1, m_krashconf->showBugReport() );
  showButton( User2, m_krashconf->showDebugger() );

  connect(this, SIGNAL(closeClicked()), SLOT(accept()));
}

Toplevel :: ~Toplevel()
{
}

QString Toplevel :: generateText() const
{
  QString str;

  if (!m_krashconf->errorDescriptionText().isEmpty())
    str += i18n("<p><b>Short description</b></p><p>%1</p>")
      .arg(m_krashconf->errorDescriptionText());

  if (!m_krashconf->signalText().isEmpty())
    str += i18n("<p><b>What is this?</b></p><p>%1</p>")
      .arg(m_krashconf->signalText());

  if (!m_krashconf->whatToDoText().isEmpty())
    str += i18n("<p><b>What can I do?</b></p><p>%1</p>")
      .arg(m_krashconf->whatToDoText());

  // check if the string is still empty. if so, display a default.
  if (str.isEmpty())
    str = i18n("<p><b>Application crashed</b></p>"
	       "<p>The program %appname crashed.</p>");

  // scan the string for %appname etc
  expandString(str);

  return str;
}

// starting bug report
void Toplevel :: slotUser1()
{
  if (bugreport) return;

  int i = KMessageBox::No;
  if ( m_krashconf->pid() != 0 )
    i = KMessageBox::warningYesNoCancel
      (0,
       i18n("<p>Do you want to generate a "
	    "backtrace? This will help the "
	    "developers to figure out what went "
	    "wrong.</p>\n"
	    "<p>Unfortantly this will take some "
	    "time on slow machines.</p>"
	    "<p><b>Note: A backtrace is not a "
	    "substitute for a proper description "
	    "the bug and information on how to "
	    "reproduce it. It is not possible "
	    "to fix the bug without a proper "
	    "description.</b></p>"),
       i18n("Include Backtrace"));

    if (i == KMessageBox::Cancel) return;

  bugreport = new DrKBugReport(0, true, m_krashconf->aboutData());

  if (i == KMessageBox::Yes) {
    QApplication::setOverrideCursor ( waitCursor );

    // generate the backtrace
    BackTrace *backtrace = new BackTrace(m_krashconf, this);
    connect(backtrace, SIGNAL(someError()), SLOT(slotBacktraceSomeError()));
    connect(backtrace, SIGNAL(done(const QString &)),
	    SLOT(slotBacktraceDone(const QString &)));

    backtrace->start();

    return;
  }

  int result = bugreport->exec();
  delete bugreport;
  bugreport = 0;
  if (result == KDialogBase::Accepted)
     close();
}

void Toplevel :: slotUser2()
{
  QString str = m_krashconf->debugger();
  expandString(str);

  // FIXME: Replace by KRun??
  KProcess proc;
  QStringList list = QStringList::split(' ', str);
  for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
    proc << *it;

  proc.start(KProcess::DontCare);
}

void Toplevel :: slotBacktraceDone(const QString &str)
{
  // Do not translate.. This will be included in the _MAIL_.
  QString buf = QString::fromLatin1
    ("\n\n\nHere is a backtrace generated by DrKonqi:\n") + str;
  
  bugreport->setText(buf);

  QApplication::restoreOverrideCursor();

  bugreport->exec();
  delete bugreport;
  bugreport = 0;
}

void Toplevel :: slotBacktraceSomeError()
{
  QApplication::restoreOverrideCursor();

  KMessageBox::sorry(0, i18n("It was not possible to generate a backtrace."),
		     i18n("Backtrace not possible"));

  bugreport->exec();
  delete bugreport;
  bugreport = 0;
}

// replace some of the strings
void Toplevel :: expandString(QString &str) const
{
  int pos = -1;
  while ( (pos = str.findRev('%', pos)) != -1 ) {
    if (str.mid(pos, 8) == QString::fromLatin1("%appname"))
      str.replace(pos, 8, QString::fromLatin1(m_krashconf->appName()));
    else if (str.mid(pos, 7) == QString::fromLatin1("%signum"))
      str.replace(pos, 7, QString::number(m_krashconf->signalNumber()));
    else if (str.mid(pos, 8) == QString::fromLatin1("%signame"))
      str.replace(pos, 8, m_krashconf->signalName());
    else if (str.mid(pos, 9) == QString::fromLatin1("%progname"))
      str.replace(pos, 9, m_krashconf->programName());
    else if (str.mid(pos, 4) == QString::fromLatin1("%pid"))
      str.replace(pos, 4, QString::number(m_krashconf->pid()));
  }
}
