forked from qt-creator/qt-creator
CrashHandlerDialog: Use Layouting
Change-Id: I6579c05b20e598c28c0ef68bd6f4f76d160ee950 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -4,7 +4,7 @@ add_qtc_executable(qtcreator_crash_handler
|
||||
SOURCES
|
||||
backtracecollector.cpp backtracecollector.h
|
||||
crashhandler.cpp crashhandler.h
|
||||
crashhandlerdialog.cpp crashhandlerdialog.h crashhandlerdialog.ui
|
||||
crashhandlerdialog.cpp crashhandlerdialog.h
|
||||
main.cpp
|
||||
utils.cpp utils.h
|
||||
)
|
||||
|
||||
@@ -4,20 +4,26 @@
|
||||
#include "crashhandlerdialog.h"
|
||||
|
||||
#include "crashhandler.h"
|
||||
#include "ui_crashhandlerdialog.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
#include <utils/checkablemessagebox.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/stringutils.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QClipboard>
|
||||
#include <QIcon>
|
||||
#include <QLabel>
|
||||
#include <QProgressBar>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include <QStyle>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextEdit>
|
||||
|
||||
static const char SettingsApplication[] = "QtCreator";
|
||||
static const char SettingsKeySkipWarningAbortingBacktrace[]
|
||||
@@ -98,53 +104,110 @@ private:
|
||||
|
||||
} // anonymous
|
||||
|
||||
CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler,
|
||||
const QString &signalName,
|
||||
const QString &appName,
|
||||
QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_crashHandler(handler),
|
||||
m_ui(new Ui::CrashHandlerDialog)
|
||||
class CrashHandlerDialogPrivate
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->introLabel->setTextFormat(Qt::RichText);
|
||||
m_ui->introLabel->setOpenExternalLinks(true);
|
||||
m_ui->debugInfoEdit->setReadOnly(true);
|
||||
new StacktraceHighlighter(m_ui->debugInfoEdit->document());
|
||||
Q_DECLARE_TR_FUNCTIONS(CrashHandlerDialog)
|
||||
|
||||
m_ui->progressBar->setMinimum(0);
|
||||
m_ui->progressBar->setMaximum(0);
|
||||
m_ui->restartAppCheckBox->setText(tr("&Restart %1 on close").arg(appName));
|
||||
public:
|
||||
CrashHandlerDialogPrivate(CrashHandlerDialog *dialog, CrashHandler *handler)
|
||||
: q(dialog)
|
||||
, m_crashHandler(handler)
|
||||
, m_iconLabel(new QLabel(q))
|
||||
, m_introLabel(new QLabel(q))
|
||||
, m_progressBar(new QProgressBar(q))
|
||||
, m_debugInfoEdit(new QTextEdit(q))
|
||||
, m_restartAppCheckBox(new QCheckBox(q))
|
||||
, m_clipboardButton(new QPushButton(tr("C&opy to clipboard"), q))
|
||||
, m_reportButton(new QPushButton(tr("Report this &bug"), q))
|
||||
, m_debugButton(new QPushButton(tr("Attach and &Debug"), q))
|
||||
, m_closeButton(new QPushButton(tr("&Close"), q))
|
||||
{
|
||||
m_introLabel->setTextFormat(Qt::RichText);
|
||||
m_introLabel->setOpenExternalLinks(true);
|
||||
m_introLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |
|
||||
Qt::TextSelectableByMouse);
|
||||
|
||||
const QStyle * const style = QApplication::style();
|
||||
m_ui->closeButton->setIcon(style->standardIcon(QStyle::SP_DialogCloseButton));
|
||||
const QStyle * const style = QApplication::style();
|
||||
const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, 0);
|
||||
const QIcon icon = style->standardIcon(QStyle::SP_MessageBoxCritical);
|
||||
m_iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
|
||||
|
||||
const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, 0);
|
||||
QIcon icon = style->standardIcon(QStyle::SP_MessageBoxCritical);
|
||||
m_ui->iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
|
||||
m_progressBar->setMinimum(0);
|
||||
m_progressBar->setMaximum(0);
|
||||
|
||||
connect(m_ui->copyToClipBoardButton, &QAbstractButton::clicked,
|
||||
this, &CrashHandlerDialog::copyToClipboardClicked);
|
||||
connect(m_ui->reportBugButton, &QAbstractButton::clicked,
|
||||
m_crashHandler, &CrashHandler::openBugTracker);
|
||||
connect(m_ui->debugAppButton, &QAbstractButton::clicked,
|
||||
m_crashHandler, &CrashHandler::debugApplication);
|
||||
connect(m_ui->closeButton, &QAbstractButton::clicked, this, &CrashHandlerDialog::close);
|
||||
m_debugInfoEdit->setReadOnly(true);
|
||||
new StacktraceHighlighter(m_debugInfoEdit->document());
|
||||
|
||||
m_restartAppCheckBox->setChecked(true);
|
||||
m_clipboardButton->setToolTip(tr("Copy the whole contents to clipboard."));
|
||||
m_clipboardButton->setEnabled(false);
|
||||
m_reportButton->setToolTip(tr("Open the bug tracker web site."));
|
||||
m_reportButton->setEnabled(false);
|
||||
m_debugButton->setToolTip(tr("Debug the application with a new instance of Qt Creator. "
|
||||
"During debugging the crash handler will be hidden."));
|
||||
m_closeButton->setToolTip(tr("Quit the handler and the crashed application."));
|
||||
m_closeButton->setIcon(style->standardIcon(QStyle::SP_DialogCloseButton));
|
||||
|
||||
QObject::connect(m_clipboardButton, &QAbstractButton::clicked, q, [this] {
|
||||
Utils::setClipboardAndSelection(m_debugInfoEdit->toPlainText());
|
||||
});
|
||||
QObject::connect(m_reportButton, &QAbstractButton::clicked,
|
||||
m_crashHandler, &CrashHandler::openBugTracker);
|
||||
QObject::connect(m_debugButton, &QAbstractButton::clicked,
|
||||
m_crashHandler, &CrashHandler::debugApplication);
|
||||
QObject::connect(m_closeButton, &QAbstractButton::clicked, q, [this] {
|
||||
if (m_restartAppCheckBox->isEnabled() && m_restartAppCheckBox->isChecked())
|
||||
m_crashHandler->restartApplication();
|
||||
QCoreApplication::quit();
|
||||
});
|
||||
|
||||
using namespace Utils::Layouting;
|
||||
|
||||
Column {
|
||||
Row { m_iconLabel, m_introLabel, st },
|
||||
m_progressBar,
|
||||
m_debugInfoEdit,
|
||||
m_restartAppCheckBox,
|
||||
Row { m_clipboardButton, m_reportButton, st, m_debugButton, m_closeButton }
|
||||
}.attachTo(q);
|
||||
}
|
||||
|
||||
CrashHandlerDialog *q = nullptr;
|
||||
|
||||
CrashHandler *m_crashHandler = nullptr;
|
||||
|
||||
QLabel *m_iconLabel = nullptr;
|
||||
QLabel *m_introLabel = nullptr;
|
||||
QProgressBar *m_progressBar = nullptr;
|
||||
QTextEdit *m_debugInfoEdit = nullptr;
|
||||
QCheckBox *m_restartAppCheckBox = nullptr;
|
||||
QPushButton *m_clipboardButton = nullptr;
|
||||
QPushButton *m_reportButton = nullptr;
|
||||
QPushButton *m_debugButton = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
};
|
||||
|
||||
CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
|
||||
const QString &appName, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, d(new CrashHandlerDialogPrivate(this, handler))
|
||||
{
|
||||
d->m_restartAppCheckBox->setText(tr("&Restart %1 on close").arg(appName));
|
||||
setApplicationInfo(signalName, appName);
|
||||
resize(600, 800);
|
||||
}
|
||||
|
||||
CrashHandlerDialog::~CrashHandlerDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
|
||||
{
|
||||
// Check settings.
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
|
||||
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
|
||||
QLatin1String(SettingsApplication));
|
||||
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
|
||||
QLatin1String(SettingsApplication));
|
||||
if (settings.value(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), false).toBool())
|
||||
return true;
|
||||
|
||||
@@ -160,7 +223,7 @@ bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
|
||||
bool checkBoxSetting = false;
|
||||
const QDialogButtonBox::StandardButton button = Utils::CheckableMessageBox::question(this,
|
||||
title, message, checkBoxText, &checkBoxSetting,
|
||||
QDialogButtonBox::Yes|QDialogButtonBox::No, QDialogButtonBox::No);
|
||||
QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::No);
|
||||
if (checkBoxSetting)
|
||||
settings.setValue(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), checkBoxSetting);
|
||||
|
||||
@@ -169,46 +232,44 @@ bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
|
||||
|
||||
void CrashHandlerDialog::setToFinalState()
|
||||
{
|
||||
m_ui->progressBar->hide();
|
||||
m_ui->copyToClipBoardButton->setEnabled(true);
|
||||
m_ui->reportBugButton->setEnabled(true);
|
||||
d->m_progressBar->hide();
|
||||
d->m_clipboardButton->setEnabled(true);
|
||||
d->m_reportButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::disableRestartAppCheckBox()
|
||||
{
|
||||
m_ui->restartAppCheckBox->setDisabled(true);
|
||||
d->m_restartAppCheckBox->setDisabled(true);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::disableDebugAppButton()
|
||||
{
|
||||
m_ui->debugAppButton->setDisabled(true);
|
||||
d->m_debugButton->setDisabled(true);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::setApplicationInfo(const QString &signalName, const QString &appName)
|
||||
{
|
||||
const QString title = tr("%1 has closed unexpectedly (Signal \"%2\")").arg(appName, signalName);
|
||||
const QString introLabelContents = tr(
|
||||
"<p><b>%1.</b></p>"
|
||||
const QString introLabelContents = tr("<p><b>%1.</b></p>"
|
||||
"<p>Please file a <a href='%2'>bug report</a> with the debug information provided below.</p>")
|
||||
.arg(title, QLatin1String(URL_BUGTRACKER));
|
||||
m_ui->introLabel->setText(introLabelContents);
|
||||
d->m_introLabel->setText(introLabelContents);
|
||||
setWindowTitle(title);
|
||||
|
||||
QString revision;
|
||||
#ifdef IDE_REVISION
|
||||
revision = QLatin1Char(' ') + tr("from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10));
|
||||
revision = QLatin1Char(' ') + tr("from revision %1")
|
||||
.arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10));
|
||||
#endif
|
||||
const QString versionInformation = tr(
|
||||
"%1 %2%3, based on Qt %4 (%5 bit)\n")
|
||||
const QString versionInformation = tr("%1 %2%3, based on Qt %4 (%5 bit)\n")
|
||||
.arg(appName, QLatin1String(Core::Constants::IDE_VERSION_LONG), revision,
|
||||
QLatin1String(QT_VERSION_STR),
|
||||
QString::number(QSysInfo::WordSize));
|
||||
m_ui->debugInfoEdit->append(versionInformation);
|
||||
QLatin1String(QT_VERSION_STR), QString::number(QSysInfo::WordSize));
|
||||
d->m_debugInfoEdit->append(versionInformation);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::appendDebugInfo(const QString &chunk)
|
||||
{
|
||||
m_ui->debugInfoEdit->append(chunk);
|
||||
d->m_debugInfoEdit->append(chunk);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::selectLineWithContents(const QString &text)
|
||||
@@ -216,27 +277,15 @@ void CrashHandlerDialog::selectLineWithContents(const QString &text)
|
||||
// The selected line will be the first line visible.
|
||||
|
||||
// Go to end.
|
||||
QTextCursor cursor = m_ui->debugInfoEdit->textCursor();
|
||||
QTextCursor cursor = d->m_debugInfoEdit->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
m_ui->debugInfoEdit->setTextCursor(cursor);
|
||||
d->m_debugInfoEdit->setTextCursor(cursor);
|
||||
|
||||
// Find text by searching backwards.
|
||||
m_ui->debugInfoEdit->find(text, QTextDocument::FindCaseSensitively | QTextDocument::FindBackward);
|
||||
d->m_debugInfoEdit->find(text, QTextDocument::FindCaseSensitively | QTextDocument::FindBackward);
|
||||
|
||||
// Highlight whole line.
|
||||
cursor = m_ui->debugInfoEdit->textCursor();
|
||||
cursor = d->m_debugInfoEdit->textCursor();
|
||||
cursor.select(QTextCursor::LineUnderCursor);
|
||||
m_ui->debugInfoEdit->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::copyToClipboardClicked()
|
||||
{
|
||||
Utils::setClipboardAndSelection(m_ui->debugInfoEdit->toPlainText());
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::close()
|
||||
{
|
||||
if (m_ui->restartAppCheckBox->isEnabled() && m_ui->restartAppCheckBox->isChecked())
|
||||
m_crashHandler->restartApplication();
|
||||
QCoreApplication::quit();
|
||||
d->m_debugInfoEdit->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
@@ -5,22 +5,16 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QString;
|
||||
namespace Ui { class CrashHandlerDialog; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class CrashHandler;
|
||||
class CrashHandlerDialogPrivate;
|
||||
|
||||
class CrashHandlerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CrashHandlerDialog(CrashHandler *handler,
|
||||
const QString &signalName,
|
||||
const QString &appName,
|
||||
QWidget *parent = 0);
|
||||
CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
|
||||
const QString &appName, QWidget *parent = nullptr);
|
||||
~CrashHandlerDialog();
|
||||
|
||||
public:
|
||||
@@ -33,9 +27,5 @@ public:
|
||||
bool runDebuggerWhileBacktraceNotFinished();
|
||||
|
||||
private:
|
||||
void copyToClipboardClicked();
|
||||
void close();
|
||||
|
||||
CrashHandler *m_crashHandler;
|
||||
Ui::CrashHandlerDialog *m_ui;
|
||||
CrashHandlerDialogPrivate *d;
|
||||
};
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CrashHandlerDialog</class>
|
||||
<widget class="QDialog" name="CrashHandlerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>800</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="iconLabel">
|
||||
<property name="text">
|
||||
<string>Icon</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="introLabel">
|
||||
<property name="text">
|
||||
<string>Some useful information here...</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="debugInfoEdit"/>
|
||||
</item>
|
||||
<item alignment="Qt::AlignRight">
|
||||
<widget class="QCheckBox" name="restartAppCheckBox">
|
||||
<property name="text">
|
||||
<string>&Restart Qt Creator on close</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="copyToClipBoardButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Copy the whole contents to clipboard.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>C&opy to clipboard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reportBugButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open the bug tracker web site.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Report this &bug</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="debugAppButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Debug the application with a new instance of Qt Creator. During debugging the crash handler will be hidden.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Attach and &Debug</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="toolTip">
|
||||
<string>Quit the handler and the crashed application.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -13,7 +13,7 @@ QtcTool {
|
||||
files: [
|
||||
"backtracecollector.cpp", "backtracecollector.h",
|
||||
"crashhandler.cpp", "crashhandler.h",
|
||||
"crashhandlerdialog.cpp", "crashhandlerdialog.h", "crashhandlerdialog.ui",
|
||||
"crashhandlerdialog.cpp", "crashhandlerdialog.h",
|
||||
"main.cpp",
|
||||
"utils.cpp", "utils.h"
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user