/* ==================================================================== * 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 #include #include #include #include #include // sys #ifdef _WIN32 #include #endif // _WIN32 ErrorDialog::ErrorDialog( const sc::Exception& e, QWidget *parent, const char *name ) : super( parent, name, true ) { const sc::ExceptionStack* est = dynamic_cast(&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( "" + _q("sorry, %1 has a problem... :-(").arg(getLongAppName())+ "" ); 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("" ); 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 }