/* ====================================================================
* Copyright (c) 2003-2006, Martin Hauner
* http://subcommander.tigris.org
*
* Subcommander is licensed as described in the file doc/COPYING, which
* you should have received as part of this distribution.
* ====================================================================
*/
// sc
#include "config.h"
#include "ErrorDialog.h"
#include "MessageBox.h"
#include "Utility.h"
#include "util/Exception.h"
#include "util/ExceptionStack.h"
#include "util/ErrorCodes.h"
// qt
#include <qlayout.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qtextview.h>
#include <qgroupbox.h>
#include <qlineedit.h>
// sys
#ifdef _WIN32
#include <mapi.h>
#endif // _WIN32
ErrorDialog::ErrorDialog( const sc::Exception& e, QWidget *parent, const char *name )
: super( parent, name, true )
{
const sc::ExceptionStack* est = dynamic_cast<const sc::ExceptionStack*>(&e);
if( est )
{
setup(e.getError(),est->getStack());
}
else
{
Stackframes frames;
setup(e.getError(),frames);
}
}
ErrorDialog::ErrorDialog( const sc::Error* err, const Stackframes& stack, QWidget* parent,
const char* name ) : super( parent, name, true )
{
setup(err,stack);
}
void ErrorDialog::setup( const sc::Error* err, const Stackframes& stack )
{
setCaption( _q("%1:exception").arg(getAppName()) );
QString error = QString(err->getMessage());
// extract dump file name
const sc::Error* nested = err->getNested();
if( nested && nested->getCode() == sc::ErrDump )
{
_dump = QString(nested->getMessage());
}
QVBoxLayout *vbl = new QVBoxLayout(this,5,8);
vbl->setSpacing(10);
{
QLabel *l = new QLabel(this);
vbl->addWidget(l,0);
l->setMargin(2);
l->setText(
"<qt><font size=3><b>" +
_q("sorry, %1 has a problem... :-(").arg(getLongAppName())+
"</b></font></qt>" );
l->setAlignment( Qt::AlignCenter );
QGroupBox* gb = new QGroupBox(1,Qt::Vertical,this);
gb->setTitle( _q("crash details: ") );
gb->setInsideMargin(0);
gb->setFlat(true);
vbl->addWidget(gb);
QLabel *l2 = new QLabel(this);
vbl->addWidget(l2,0);
l2->setMargin(2);
l2->setText(error);
l2->setAlignment( Qt::AlignCenter );
l2->setPaletteBackgroundColor( QColor(255,120,120) );
QString textl3;
textl3 +=
_q("Please send this crash information and the crash dump\n"
"(%1)\n"
"to crash@subcommander.tigris.org.\n\n").arg(_dump);
textl3 +=
_q("Just press 'Send' to open your email client with a prepared email.");
textl3 +=
_q("\nIf this doesn't work please send the information manually.\nThank you.");
QLabel *l3 = new QLabel(this);
vbl->addWidget(l3,0);
l3->setMargin(2);
l3->setText(textl3);
l3->setAlignment( Qt::AlignCenter );
QGroupBox* gb2 = new QGroupBox(1,Qt::Vertical,this);
gb2->setTitle( _q("Send:") );
gb2->setInsideMargin(0);
gb2->setFlat(true);
vbl->addWidget(gb2);
_text = new QTextEdit(this);
vbl->addWidget(_text,3);
//te->setReadOnly(true);
_text->setLineWidth(1);
_text->setMargin(1);
_text->setWordWrap(QTextEdit::NoWrap);
_text->setFrameStyle( QFrame::Box | QFrame::Sunken );
_text->setMinimumWidth(460);
_text->setMinimumHeight(200);
//te->setPaper( backgroundColor() );
QString text;
text += _q("email:\n");
text += _q("crash@subcommander.tigris.org");
text += _q("\n\nCrash Dump:\n");
text += _dump;
text += "\n\n";
text += _q("Hi,\n\n%1 crashed when I ...\n\n").arg(getLongAppName());
text += _q("<If you are able to reproduce the crash please describe how. Thank you!>" );
text += "\n\n\n";
text += "\n\n";
text += _q("*** crash information: ***");
text += "\n\n" + getAppName() + ":exception - " + error + "\n\n";
for( Stackframes::const_iterator it = stack.begin(); it != stack.end(); it++ )
{
const Stackframe& f = *it;
if(!f._error)
{
// address
QString addr;
text += "0x" +addr.setNum(f._addr,16).rightJustify(16,'0');
//+":0x" + addr.setNum(f._addrSeg).rightJustify(4,'0');
if(f._symbol)
{
text += " : " +QString(f._symbolName);
}
else
{
text += " : " +QString("unknown");
}
if(f._module)
{
text += " " + QString(f._moduleName);
}
else
{
text += " " + QString("unknown");
}
text += "\n ";
if(f._line)
{
text += addr.setNum(f._lineNr);
text += " + 0x" + addr.setNum(f._lineDisp,16) + " (";
text += QString(f._fileName) + ")";
text += "\n ";
}
//else
//{
//text += QString("0")+ " (";
//text += QString("unknown") + ")";
//}
}
text += "\n";
}
_text->setText( text );
QHBoxLayout* hu = new QHBoxLayout;
vbl->addLayout(hu);
{
// eats extra space, so the buttons keep their size
hu->addStretch(1);
QPushButton* send = new QPushButton(this);
send->setText( _q("S&end") );
#ifdef _WIN32
send->setDefault(true);
#else
send->setDefault(false);
#endif // _WIN32
hu->addWidget(send);
connect( send, SIGNAL(clicked()), SLOT(send()) );
QPushButton* cancel = new QPushButton(this);
cancel->setText( _q("&Cancel") );
hu->addWidget(cancel);
connect( cancel, SIGNAL(clicked()), SLOT(reject()) );
}
}
}
ErrorDialog::~ErrorDialog()
{
}
static const char* copyString( const QString& s )
{
QCString qs = s.local8Bit();
char* result = (char*)calloc( qs.length()+1, 1 );
strncpy( result, (const char*)qs, qs.length() );
return result;
}
void ErrorDialog::send()
{
#if _WIN32
typedef ULONG (FAR PASCAL *MAPISendMail)(
LHANDLE lhSession,ULONG ulUIParam,lpMapiMessage lpMessage,FLAGS flFlags,ULONG ulReserved);
HMODULE hMapi = LoadLibrary( "MAPI32.dll" );
if( hMapi )
{
MAPISendMail MapiSendMail = (MAPISendMail)GetProcAddress( hMapi, "MAPISendMail" );
if( MapiSendMail )
{
MapiFileDesc attachment =
{
0, // reserved
0, // data file
(ULONG)-1, // position
(LPSTR)copyString(_dump), // full path
NULL, // display name
NULL // file details
};
QString target(_q("crash@subcommander.tigris.org"));
MapiRecipDesc recipient =
{
0, // reserved
MAPI_TO, // recipient class
NULL, // name
(LPSTR)copyString(target), // address
0, // entry id size
NULL // entry id
};
MapiMessage message =
{
0, // reserved
(LPSTR)copyString(_q("crash..!")), // subject
(LPSTR)copyString(_text->text()), // message
NULL, // message type
NULL, // date
NULL, // conversation ID
0L, // flags
NULL, // originator
1, // recipient count
&recipient, // recipents
1, // attachment count
&attachment // attachments
};
ULONG res = MapiSendMail( 0L, 0L, &message, MAPI_DIALOG, 0L );
}
FreeLibrary(hMapi);
}
#endif // _WIN32
}
syntax highlighted by Code2HTML, v. 0.9.1