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
backtracecollector.cpp backtracecollector.h
crashhandler.cpp crashhandler.h
crashhandlerdialog.cpp crashhandlerdialog.h crashhandlerdialog.ui
crashhandlerdialog.cpp crashhandlerdialog.h
main.cpp
utils.cpp utils.h
)

View File

@@ -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);
}

View File

@@ -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;
};

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: [
"backtracecollector.cpp", "backtracecollector.h",
"crashhandler.cpp", "crashhandler.h",
"crashhandlerdialog.cpp", "crashhandlerdialog.h", "crashhandlerdialog.ui",
"crashhandlerdialog.cpp", "crashhandlerdialog.h",
"main.cpp",
"utils.cpp", "utils.h"
]