CrashHandlerDialog: Use Layouting

Change-Id: I6579c05b20e598c28c0ef68bd6f4f76d160ee950
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-11-16 18:46:55 +01:00
parent 83720540a1
commit b31249d753
5 changed files with 119 additions and 230 deletions

View File

@@ -4,7 +4,7 @@ add_qtc_executable(qtcreator_crash_handler
SOURCES SOURCES
backtracecollector.cpp backtracecollector.h backtracecollector.cpp backtracecollector.h
crashhandler.cpp crashhandler.h crashhandler.cpp crashhandler.h
crashhandlerdialog.cpp crashhandlerdialog.h crashhandlerdialog.ui crashhandlerdialog.cpp crashhandlerdialog.h
main.cpp main.cpp
utils.cpp utils.h utils.cpp utils.h
) )

View File

@@ -4,20 +4,26 @@
#include "crashhandlerdialog.h" #include "crashhandlerdialog.h"
#include "crashhandler.h" #include "crashhandler.h"
#include "ui_crashhandlerdialog.h"
#include "utils.h" #include "utils.h"
#include <app/app_version.h> #include <app/app_version.h>
#include <utils/checkablemessagebox.h> #include <utils/checkablemessagebox.h>
#include <utils/layoutbuilder.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <QApplication>
#include <QCheckBox>
#include <QClipboard> #include <QClipboard>
#include <QIcon> #include <QIcon>
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>
#include <QSettings> #include <QSettings>
#include <QStyle> #include <QStyle>
#include <QSyntaxHighlighter> #include <QSyntaxHighlighter>
#include <QTextCharFormat> #include <QTextCharFormat>
#include <QTextEdit>
static const char SettingsApplication[] = "QtCreator"; static const char SettingsApplication[] = "QtCreator";
static const char SettingsKeySkipWarningAbortingBacktrace[] static const char SettingsKeySkipWarningAbortingBacktrace[]
@@ -98,53 +104,110 @@ private:
} // anonymous } // anonymous
CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, class CrashHandlerDialogPrivate
const QString &signalName,
const QString &appName,
QWidget *parent) :
QDialog(parent),
m_crashHandler(handler),
m_ui(new Ui::CrashHandlerDialog)
{ {
m_ui->setupUi(this); Q_DECLARE_TR_FUNCTIONS(CrashHandlerDialog)
m_ui->introLabel->setTextFormat(Qt::RichText);
m_ui->introLabel->setOpenExternalLinks(true);
m_ui->debugInfoEdit->setReadOnly(true);
new StacktraceHighlighter(m_ui->debugInfoEdit->document());
m_ui->progressBar->setMinimum(0); public:
m_ui->progressBar->setMaximum(0); CrashHandlerDialogPrivate(CrashHandlerDialog *dialog, CrashHandler *handler)
m_ui->restartAppCheckBox->setText(tr("&Restart %1 on close").arg(appName)); : 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(); const QStyle * const style = QApplication::style();
m_ui->closeButton->setIcon(style->standardIcon(QStyle::SP_DialogCloseButton)); 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); m_progressBar->setMinimum(0);
QIcon icon = style->standardIcon(QStyle::SP_MessageBoxCritical); m_progressBar->setMaximum(0);
m_ui->iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
connect(m_ui->copyToClipBoardButton, &QAbstractButton::clicked, m_debugInfoEdit->setReadOnly(true);
this, &CrashHandlerDialog::copyToClipboardClicked); new StacktraceHighlighter(m_debugInfoEdit->document());
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_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); setApplicationInfo(signalName, appName);
resize(600, 800);
} }
CrashHandlerDialog::~CrashHandlerDialog() CrashHandlerDialog::~CrashHandlerDialog()
{ {
delete m_ui; delete d;
} }
bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished() bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
{ {
// Check settings. // Check settings.
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QSettings settings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR), QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
QLatin1String(SettingsApplication)); QLatin1String(SettingsApplication));
if (settings.value(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), false).toBool()) if (settings.value(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), false).toBool())
return true; return true;
@@ -160,7 +223,7 @@ bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
bool checkBoxSetting = false; bool checkBoxSetting = false;
const QDialogButtonBox::StandardButton button = Utils::CheckableMessageBox::question(this, const QDialogButtonBox::StandardButton button = Utils::CheckableMessageBox::question(this,
title, message, checkBoxText, &checkBoxSetting, title, message, checkBoxText, &checkBoxSetting,
QDialogButtonBox::Yes|QDialogButtonBox::No, QDialogButtonBox::No); QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::No);
if (checkBoxSetting) if (checkBoxSetting)
settings.setValue(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), checkBoxSetting); settings.setValue(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), checkBoxSetting);
@@ -169,46 +232,44 @@ bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
void CrashHandlerDialog::setToFinalState() void CrashHandlerDialog::setToFinalState()
{ {
m_ui->progressBar->hide(); d->m_progressBar->hide();
m_ui->copyToClipBoardButton->setEnabled(true); d->m_clipboardButton->setEnabled(true);
m_ui->reportBugButton->setEnabled(true); d->m_reportButton->setEnabled(true);
} }
void CrashHandlerDialog::disableRestartAppCheckBox() void CrashHandlerDialog::disableRestartAppCheckBox()
{ {
m_ui->restartAppCheckBox->setDisabled(true); d->m_restartAppCheckBox->setDisabled(true);
} }
void CrashHandlerDialog::disableDebugAppButton() void CrashHandlerDialog::disableDebugAppButton()
{ {
m_ui->debugAppButton->setDisabled(true); d->m_debugButton->setDisabled(true);
} }
void CrashHandlerDialog::setApplicationInfo(const QString &signalName, const QString &appName) void CrashHandlerDialog::setApplicationInfo(const QString &signalName, const QString &appName)
{ {
const QString title = tr("%1 has closed unexpectedly (Signal \"%2\")").arg(appName, signalName); const QString title = tr("%1 has closed unexpectedly (Signal \"%2\")").arg(appName, signalName);
const QString introLabelContents = tr( const QString introLabelContents = tr("<p><b>%1.</b></p>"
"<p><b>%1.</b></p>"
"<p>Please file a <a href='%2'>bug report</a> with the debug information provided below.</p>") "<p>Please file a <a href='%2'>bug report</a> with the debug information provided below.</p>")
.arg(title, QLatin1String(URL_BUGTRACKER)); .arg(title, QLatin1String(URL_BUGTRACKER));
m_ui->introLabel->setText(introLabelContents); d->m_introLabel->setText(introLabelContents);
setWindowTitle(title); setWindowTitle(title);
QString revision; QString revision;
#ifdef IDE_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 #endif
const QString versionInformation = tr( const QString versionInformation = tr("%1 %2%3, based on Qt %4 (%5 bit)\n")
"%1 %2%3, based on Qt %4 (%5 bit)\n")
.arg(appName, QLatin1String(Core::Constants::IDE_VERSION_LONG), revision, .arg(appName, QLatin1String(Core::Constants::IDE_VERSION_LONG), revision,
QLatin1String(QT_VERSION_STR), QLatin1String(QT_VERSION_STR), QString::number(QSysInfo::WordSize));
QString::number(QSysInfo::WordSize)); d->m_debugInfoEdit->append(versionInformation);
m_ui->debugInfoEdit->append(versionInformation);
} }
void CrashHandlerDialog::appendDebugInfo(const QString &chunk) void CrashHandlerDialog::appendDebugInfo(const QString &chunk)
{ {
m_ui->debugInfoEdit->append(chunk); d->m_debugInfoEdit->append(chunk);
} }
void CrashHandlerDialog::selectLineWithContents(const QString &text) 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. // The selected line will be the first line visible.
// Go to end. // Go to end.
QTextCursor cursor = m_ui->debugInfoEdit->textCursor(); QTextCursor cursor = d->m_debugInfoEdit->textCursor();
cursor.movePosition(QTextCursor::End); cursor.movePosition(QTextCursor::End);
m_ui->debugInfoEdit->setTextCursor(cursor); d->m_debugInfoEdit->setTextCursor(cursor);
// Find text by searching backwards. // 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. // Highlight whole line.
cursor = m_ui->debugInfoEdit->textCursor(); cursor = d->m_debugInfoEdit->textCursor();
cursor.select(QTextCursor::LineUnderCursor); cursor.select(QTextCursor::LineUnderCursor);
m_ui->debugInfoEdit->setTextCursor(cursor); d->m_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();
} }

View File

@@ -5,22 +5,16 @@
#include <QDialog> #include <QDialog>
QT_BEGIN_NAMESPACE
class QString;
namespace Ui { class CrashHandlerDialog; }
QT_END_NAMESPACE
class CrashHandler; class CrashHandler;
class CrashHandlerDialogPrivate;
class CrashHandlerDialog : public QDialog class CrashHandlerDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CrashHandlerDialog(CrashHandler *handler, CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
const QString &signalName, const QString &appName, QWidget *parent = nullptr);
const QString &appName,
QWidget *parent = 0);
~CrashHandlerDialog(); ~CrashHandlerDialog();
public: public:
@@ -33,9 +27,5 @@ public:
bool runDebuggerWhileBacktraceNotFinished(); bool runDebuggerWhileBacktraceNotFinished();
private: private:
void copyToClipboardClicked(); CrashHandlerDialogPrivate *d;
void close();
CrashHandler *m_crashHandler;
Ui::CrashHandlerDialog *m_ui;
}; };

View File

@@ -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>&amp;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&amp;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 &amp;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 &amp;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>&amp;Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -13,7 +13,7 @@ QtcTool {
files: [ files: [
"backtracecollector.cpp", "backtracecollector.h", "backtracecollector.cpp", "backtracecollector.h",
"crashhandler.cpp", "crashhandler.h", "crashhandler.cpp", "crashhandler.h",
"crashhandlerdialog.cpp", "crashhandlerdialog.h", "crashhandlerdialog.ui", "crashhandlerdialog.cpp", "crashhandlerdialog.h",
"main.cpp", "main.cpp",
"utils.cpp", "utils.h" "utils.cpp", "utils.h"
] ]