when a new activity is added, don't move more than necessary to show it
[kdebase.git] / runtime / drkonqi / debugger.cpp
blobdcd4531c193dbee38e7811b637fc9ab09807855b
1 /*****************************************************************
2 * drkonqi - The KDE Crash Handler
4 * Copyright (C) 2000-2003 Hans Petter Bieker <bieker@kde.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *****************************************************************/
28 #include "debugger.h"
30 #include <QLabel>
31 #include <QTextStream>
32 #include <QVBoxLayout>
33 #include <QHBoxLayout>
35 #include <kdialog.h>
36 #include <klocale.h>
37 #include <kglobal.h>
38 #include <kglobalsettings.h>
39 #include <kfiledialog.h>
40 #include <kmessagebox.h>
41 #include <kpushbutton.h>
42 #include <kstandardguiitem.h>
43 #include <ktextbrowser.h>
44 #include <ktemporaryfile.h>
46 #include "backtracegdb.h"
47 #include "krashconf.h"
48 #include "debugger.moc"
50 KrashDebugger :: KrashDebugger (const KrashConfig *krashconf, QWidget *parent)
51 : QWidget( parent ),
52 m_krashconf(krashconf),
53 m_proctrace(0)
55 QVBoxLayout *vbox = new QVBoxLayout( this );
56 vbox->setSpacing( KDialog::spacingHint() );
57 vbox->setMargin( 0 );
59 m_backtrace = new KTextBrowser(this);
60 m_backtrace->setFont(KGlobalSettings::fixedFont());
62 vbox->addWidget(m_backtrace);
64 QHBoxLayout *hbox = new QHBoxLayout();
65 hbox->setMargin( 0 );
66 hbox->setSpacing( KDialog::spacingHint() );
68 m_status = new QLabel( this );
69 //m_copyButton = new KPushButton( KStandardGuiItem::copy(), w );
70 hbox->addWidget(m_status, 1);
71 KGuiItem item( i18n( "C&opy" ), QLatin1String( "edit-copy" ) );
72 m_copyButton = new KPushButton( item, this );
73 connect( m_copyButton, SIGNAL( clicked() ), this, SLOT( slotCopy() ) );
74 m_copyButton->setEnabled( false );
75 hbox->addWidget(m_copyButton);
76 m_saveButton = new KPushButton( m_krashconf->safeMode() ? KStandardGuiItem::save() : KStandardGuiItem::saveAs(), this );
77 connect( m_saveButton, SIGNAL( clicked() ), this, SLOT( slotSave() ) );
78 m_saveButton->setEnabled( false );
79 hbox->addWidget(m_saveButton);
81 vbox->addLayout(hbox);
83 QString tmp = i18n( "Application: %progname (%execname), signal %signame" ) + '\n';
84 krashconf->expandString( tmp, KrashConfig::ExpansionUsagePlainText );
85 m_prependText = tmp;
88 KrashDebugger :: ~KrashDebugger()
90 // This will SIGKILL gdb and SIGCONT program which crashed.
91 // delete m_proctrace;
94 void KrashDebugger :: slotDone(const QString& str)
96 m_status->setText(i18nc("debugging finished", "Backtrace loaded."));
97 m_copyButton->setEnabled( true );
98 m_saveButton->setEnabled( true );
99 m_backtrace->setPlainText( m_prependText + str ); // replace with possibly post-processed backtrace
102 void KrashDebugger :: slotCopy()
104 m_backtrace->selectAll();
105 m_backtrace->copy();
108 void KrashDebugger :: slotSave()
110 if (m_krashconf->safeMode())
112 KTemporaryFile tf;
113 tf.setPrefix("/tmp/");
114 tf.setSuffix(".kcrash");
115 tf.setAutoRemove(false);
116 if (tf.open())
118 QTextStream textStream( &tf );
119 textStream << m_backtrace->toPlainText();
120 textStream.flush();
121 KMessageBox::information(this, i18n("Backtrace saved to <filename>%1</filename>.", tf.fileName()));
123 else
125 KMessageBox::sorry(this, i18n("Cannot create a file to save the backtrace in"));
128 else
130 QString defname = m_krashconf->execName() + ".kcrash";
131 if( defname.contains( '/' ))
132 defname = defname.mid( defname.lastIndexOf( '/' ) + 1 );
133 QString filename = KFileDialog::getSaveFileName( defname, QString(), this, i18n("Select Filename"));
134 if (!filename.isEmpty())
136 QFile f(filename);
138 if (f.exists()) {
139 if (KMessageBox::Cancel ==
140 KMessageBox::warningContinueCancel( 0,
141 i18n( "A file named <filename>%1</filename> already exists. "
142 "Are you sure you want to overwrite it?", filename ),
143 i18n( "Overwrite File?" ),
144 KGuiItem( i18n( "&Overwrite" ) ) ))
145 return;
148 if (f.open(QIODevice::WriteOnly))
150 QTextStream ts(&f);
151 ts << m_backtrace->toPlainText();
152 f.close();
154 else
156 KMessageBox::sorry(this, i18n("Cannot open file <filename>%1</filename> for writing.", filename));
162 void KrashDebugger :: slotSomeError()
164 KMessageBox::sorry(this, i18n("Unable to create a valid backtrace.") + "\n\n"
165 + i18n("This backtrace appears to be of no use.\n"
166 "This is probably because your packages are built in a way "
167 "which prevents creation of proper backtraces, or the stack frame "
168 "was seriously corrupted in the crash.\n\n"));
169 m_status->setText(i18n("Unable to create a valid backtrace."));
170 m_backtrace->setPlainText(i18n("This backtrace appears to be of no use.\n"
171 "This is probably because your packages are built in a way "
172 "which prevents creation of proper backtraces, or the stack frame "
173 "was seriously corrupted in the crash.\n\n" )
174 + m_backtrace->toPlainText());
177 void KrashDebugger :: slotAppend(const QString &str)
179 m_status->setText(i18n("Loading backtrace..."));
181 // append doesn't work here because it will add a newline as well
182 m_backtrace->setPlainText(m_backtrace->toPlainText() + str);
185 void KrashDebugger :: showEvent(QShowEvent *e)
187 QWidget::showEvent(e);
188 startDebugger();
191 void KrashDebugger :: startDebugger()
193 // Only start one copy
194 if (m_proctrace || !m_backtrace->toPlainText().isEmpty())
195 return;
197 QString msg;
198 bool checks = performChecks( &msg );
199 if( !checks && !m_krashconf->disableChecks())
201 m_backtrace->setPlainText( m_prependText +
202 i18n( "The following options are enabled:\n\n" )
203 + msg
204 + i18n( "\nAs the usage of these options is not recommended -"
205 " because they can, in rare cases, be responsible for KDE problems - a backtrace"
206 " will not be generated.\n"
207 "You need to turn these options off and reproduce"
208 " the problem again in order to get a backtrace.\n" ));
209 m_status->setText( i18n( "Backtrace will not be created."));
210 return;
213 m_proctrace = BackTrace::create(m_krashconf, this);
215 if( !msg.isEmpty())
217 m_prependText += msg + '\n';
218 m_backtrace->setPlainText( m_prependText );
220 m_status->setText(i18n("Loading symbols..."));
222 connect(m_proctrace, SIGNAL(append(const QString &)),
223 SLOT(slotAppend(const QString &)));
224 connect(m_proctrace, SIGNAL(done(const QString&)), SLOT(slotDone(const QString&)));
225 connect(m_proctrace, SIGNAL(someError()), SLOT(slotSomeError()));
227 m_proctrace->start();
230 // this function check for "dangerous" settings, returns false
231 // and message in case some of them are activated
232 bool KrashDebugger::performChecks( QString* msg )
234 bool ret = true;
235 KConfig kdedcfg( QLatin1String( "kdedrc" ) );
236 if( kdedcfg.group("General").readEntry( "DelayedCheck", false))
238 // ret = false; it's not that dangerous
239 *msg += i18n( "System configuration startup check disabled.\n" );
241 return ret;
244 QSize KrashDebugger::sizeHint() const
246 // reduce inital size a bit (the text browser is affected)
247 return QSize(QWidget::sizeHint().width(), QWidget::sizeHint().height() / 3 * 2);