Add Crashpad to Qt Creator and Qt Design Studio

Fixes: QDS-2748
Change-Id: I87e25682f066d167eebfd7b78c46c166e5062e11
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Mahmoud Badri
2020-09-21 12:58:35 +03:00
parent 89ad72c789
commit cc7be5724a
15 changed files with 493 additions and 19 deletions

View File

@@ -44,6 +44,13 @@
#include <qtsystemexceptionhandler.h>
#endif
#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
#define NOMINMAX
#include "client/crashpad_client.h"
#include "client/crash_report_database.h"
#include "client/settings.h"
#endif
#ifdef Q_OS_WIN
#include <Windows.h>
#endif
@@ -98,6 +105,44 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS
}
#endif
#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
bool startCrashpad()
{
using namespace crashpad;
// Cache directory that will store crashpad information and minidumps
base::FilePath database(L"crashpad_reports");
base::FilePath handler(L"crashpad_handler.exe");
// URL used to submit minidumps to
std::string url(CRASHPAD_BACKEND_URL);
// Optional annotations passed via --annotations to the handler
std::map<std::string, std::string> annotations;
annotations["qt-version"] = QT_VERSION_STR;
// Optional arguments to pass to the handler
std::vector<std::string> arguments;
CrashpadClient *client = new CrashpadClient();
bool success = client->StartHandler(
handler,
database,
database,
url,
annotations,
arguments,
/* restartable */ true,
/* asynchronous_start */ true
);
// TODO: research using this method, should avoid creating a separate CrashpadClient for the
// puppet (needed only on windows according to docs).
// client->SetHandlerIPCPipe(L"\\\\.\\pipe\\qml2puppet");
return success;
}
#endif
int internalMain(QGuiApplication *application)
{
QCoreApplication::setOrganizationName("QtProject");
@@ -180,6 +225,10 @@ int internalMain(QGuiApplication *application)
QtSystemExceptionHandler systemExceptionHandler(libexecPath);
#endif
#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
startCrashpad();
#endif
new QmlDesigner::Qt5NodeInstanceClientProxy(application);
#if defined(Q_OS_WIN) && defined(QT_NO_DEBUG)

View File

@@ -79,3 +79,54 @@ if (APPLE)
DESTINATION ${IDE_DATA_PATH}
)
endif()
# Crashpad
set(CRASHPAD_BACKEND_URL "" CACHE STRING "Crashpad backend URL")
set(CRASHPAD_SRC "" CACHE STRING "Path to Crashpad source code")
set(CRASHPAD_BUILD "" CACHE STRING "Path to Crashpad build folder")
if (CRASHPAD_BACKEND_URL
AND CRASHPAD_SRC
AND EXISTS "${CRASHPAD_SRC}"
AND CRASHPAD_BUILD
AND EXISTS "${CRASHPAD_BUILD}"
AND (WIN32 OR APPLE)) # LINUX isn't supported for now
target_compile_definitions(qtcreator PRIVATE
CRASHPAD_BACKEND_URL="${CRASHPAD_BACKEND_URL}"
ENABLE_CRASHPAD
WIN32_LEAN_AND_MEAN) # It comes usually with precompiled header, but at the installer they are disabled
target_include_directories(qtcreator PRIVATE
"${CRASHPAD_SRC}"
"${CRASHPAD_SRC}/third_party/mini_chromium/mini_chromium")
if (WIN32)
target_link_libraries(qtcreator PUBLIC ${CRASHPAD_BUILD}/obj/third_party/mini_chromium/mini_chromium/base/base.lib
${CRASHPAD_BUILD}/obj/util/util.lib
${CRASHPAD_BUILD}/obj/client/client.lib
advapi32)
install(FILES ${CRASHPAD_BUILD}/crashpad_handler.exe DESTINATION "${IDE_LIBEXEC_PATH}")
elseif(APPLE)
find_library(FWbsm bsm)
target_link_libraries(qtcreator PUBLIC ${CRASHPAD_BUILD}/obj/third_party/mini_chromium/mini_chromium/base/libbase.a
${CRASHPAD_BUILD}/obj/util/libutil.a
${CRASHPAD_BUILD}/obj/client/libclient.a
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.child_portServer.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.child_portUser.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.excServer.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.excUser.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.mach_excServer.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.mach_excUser.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.notifyServer.o
${CRASHPAD_BUILD}/obj/out/Default/gen/util/mach/mig_output.notifyUser.o
${FWbsm} ${FWAppKit} ${FWIOKit} ${FWSecurity})
install(FILES ${CRASHPAD_BUILD}/crashpad_handler DESTINATION "${IDE_LIBEXEC_PATH}")
elseif(UNIX)
# TODO: Crashpad is not well supported on linux currently
target_link_libraries(qtcreator PUBLIC ${CRASHPAD_BUILD}/obj/third_party/mini_chromium/mini_chromium/base/libbase.a
${CRASHPAD_BUILD}/obj/util/libutil.a
${CRASHPAD_BUILD}/obj/client/libclient.a)
install(FILES ${CRASHPAD_BUILD}/crashpad_handler DESTINATION "${IDE_LIBEXEC_PATH}")
endif()
endif()

View File

@@ -69,6 +69,13 @@
#include <qtsystemexceptionhandler.h>
#endif
#ifdef ENABLE_CRASHPAD
#define NOMINMAX
#include "client/crashpad_client.h"
#include "client/crash_report_database.h"
#include "client/settings.h"
#endif
#ifdef Q_OS_LINUX
#include <malloc.h>
#endif
@@ -455,6 +462,54 @@ QStringList lastSessionArgument()
return hasProjectExplorer ? QStringList({"-lastsession"}) : QStringList();
}
#ifdef ENABLE_CRASHPAD
bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
{
using namespace crashpad;
// Cache directory that will store crashpad information and minidumps
QString databasePath = QDir::cleanPath(libexecPath + "/crashpad_reports");
QString handlerPath = QDir::cleanPath(libexecPath + "/crashpad_handler");
#ifdef Q_OS_WIN
handlerPath += ".exe";
base::FilePath database(databasePath.toStdWString());
base::FilePath handler(handlerPath.toStdWString());
#elif defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
base::FilePath database(databasePath.toStdString());
base::FilePath handler(handlerPath.toStdString());
#endif
std::unique_ptr<CrashReportDatabase> db = CrashReportDatabase::Initialize(database);
if (db && db->GetSettings())
db->GetSettings()->SetUploadsEnabled(crashReportingEnabled);
// URL used to submit minidumps to
std::string url(CRASHPAD_BACKEND_URL);
// Optional annotations passed via --annotations to the handler
std::map<std::string, std::string> annotations;
annotations["app-version"] = Core::Constants::IDE_VERSION_DISPLAY;
annotations["qt-version"] = QT_VERSION_STR;
// Optional arguments to pass to the handler
std::vector<std::string> arguments;
CrashpadClient *client = new CrashpadClient();
bool success = client->StartHandler(
handler,
database,
database,
url,
annotations,
arguments,
/* restartable */ true,
/* asynchronous_start */ true
);
return success;
}
#endif
int main(int argc, char **argv)
{
Restarter restarter(argc, argv);
@@ -493,7 +548,7 @@ int main(int argc, char **argv)
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
#ifdef Q_OS_MAC
#ifdef Q_OS_MACOS
// increase the number of file that can be opened in Qt Creator.
struct rlimit rl;
getrlimit(RLIMIT_NOFILE, &rl);
@@ -562,6 +617,11 @@ int main(int argc, char **argv)
CrashHandlerSetup::EnableRestart, libexecPath);
#endif
#ifdef ENABLE_CRASHPAD
bool crashReportingEnabled = settings->value("CrashReportingEnabled", false).toBool();
startCrashpad(libexecPath, crashReportingEnabled);
#endif
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
app.setAttribute(Qt::AA_DisableWindowContextHelpButton);

View File

@@ -185,6 +185,17 @@ extend_qtc_plugin(Core
SOURCES progressmanager/progressmanager_x11.cpp
)
if (CRASHPAD_BACKEND_URL
AND CRASHPAD_SRC
AND EXISTS "${CRASHPAD_SRC}"
AND CRASHPAD_BUILD
AND EXISTS "${CRASHPAD_BUILD}"
AND (WIN32 OR APPLE)) # LINUX isn't supported for now
extend_qtc_plugin(Core
DEFINES ENABLE_CRASHPAD
)
endif()
if ((NOT WIN32) AND (NOT APPLE))
# install logo
foreach(size 16 24 32 48 64 128 256 512)

View File

@@ -49,6 +49,7 @@
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/infobar.h>
#include <utils/macroexpander.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -62,6 +63,7 @@
#include <QDebug>
#include <QDir>
#include <QJsonObject>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QSettings>
@@ -75,6 +77,7 @@ using namespace Utils;
static CorePlugin *m_instance = nullptr;
const char kWarnCrashReportingSetting[] = "WarnCrashReporting";
const char kEnvironmentChanges[] = "Core/EnvironmentChanges";
void CorePlugin::setupSystemEnvironment()
@@ -234,6 +237,11 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
Utils::PathChooser::setAboutToShowContextMenuHandler(&CorePlugin::addToPathChooserContextMenu);
#ifdef ENABLE_CRASHPAD
connect(ICore::instance(), &ICore::coreOpened, this, &CorePlugin::warnAboutCrashReporing,
Qt::QueuedConnection);
#endif
return true;
}
@@ -379,6 +387,59 @@ void CorePlugin::checkSettings()
showMsgBox(errorMsg, QMessageBox::Critical);
}
void CorePlugin::warnAboutCrashReporing()
{
if (!ICore::infoBar()->canInfoBeAdded(kWarnCrashReportingSetting))
return;
QString warnStr = ICore::settings()->value("CrashReportingEnabled", false).toBool()
? tr("%1 collects crash reports for the sole purpose of fixing bugs. "
"To disable this feature go to %2.")
: tr("%1 can collect crash reports for the sole purpose of fixing bugs. "
"to enable this feature go to %2.");
if (Utils::HostOsInfo::isMacHost()) {
warnStr = warnStr.arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(Core::Constants::IDE_DISPLAY_NAME + tr(" > Preferences > Environment > System"));
} else {
warnStr = warnStr.arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(tr("Tools > Options > Environment > System"));
}
Utils::InfoBarEntry info(kWarnCrashReportingSetting, warnStr,
Utils::InfoBarEntry::GlobalSuppression::Enabled);
info.setCustomButtonInfo(tr("Configure..."), [] {
ICore::infoBar()->removeInfo(kWarnCrashReportingSetting);
ICore::infoBar()->globallySuppressInfo(kWarnCrashReportingSetting);
ICore::showOptionsDialog(Core::Constants::SETTINGS_ID_SYSTEM);
});
info.setDetailsWidgetCreator([]() -> QWidget * {
auto label = new QLabel;
label->setWordWrap(true);
label->setOpenExternalLinks(true);
label->setText(msgCrashpadInformation());
label->setContentsMargins(0, 0, 0, 8);
return label;
});
ICore::infoBar()->addInfo(info);
}
// static
QString CorePlugin::msgCrashpadInformation()
{
return tr("%1 uses Google Crashpad for collecting crashes and sending them to our backend "
"for processing. Crashpad may capture arbitrary contents from crashed process "
"memory, including user sensitive information, URLs, and whatever other content "
"users have trusted %1 with. The collected crash reports are however only used "
"for the sole purpose of fixing bugs.").arg(Core::Constants::IDE_DISPLAY_NAME)
+ "<br><br>" + tr("More information:")
+ "<br><a href='https://chromium.googlesource.com/crashpad/crashpad/+/master/doc/"
"overview_design.md'>" + tr("Crashpad Overview") + "</a>"
"<br><a href='https://sentry.io/security/'>" + tr("%1 security policy").arg("Sentry.io")
+ "</a>";
}
ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
{
Find::aboutToShutdown();

View File

@@ -68,6 +68,7 @@ public:
static Utils::Environment startupSystemEnvironment();
static Utils::EnvironmentItems environmentChanges();
static void setEnvironmentChanges(const Utils::EnvironmentItems &changes);
static QString msgCrashpadInformation();
public slots:
void fileOpenRequest(const QString&);
@@ -89,6 +90,7 @@ private:
static void addToPathChooserContextMenu(Utils::PathChooser *pathChooser, QMenu *menu);
static void setupSystemEnvironment();
void checkSettings();
void warnAboutCrashReporing();
MainWindow *m_mainWindow = nullptr;
EditMode *m_editMode = nullptr;

View File

@@ -482,6 +482,14 @@ QString ICore::libexecPath()
return QDir::cleanPath(QApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH);
}
QString ICore::crashReportsPath()
{
if (Utils::HostOsInfo::isMacHost())
return libexecPath() + "/crashpad_reports/completed";
else
return libexecPath() + "/crashpad_reports/reports";
}
static QString clangIncludePath(const QString &clangVersion)
{
return "/lib/clang/" + clangVersion + "/include";

View File

@@ -99,6 +99,7 @@ public:
static QString cacheResourcePath();
static QString installerResourcePath();
static QString libexecPath();
static QString crashReportsPath();
static QString versionString();

View File

@@ -27,6 +27,7 @@
#include "coreconstants.h"
#include "coreplugin.h"
#include "editormanager/editormanager_p.h"
#include "dialogs/restartdialog.h"
#include "fileutils.h"
#include "icore.h"
#include "iversioncontrol.h"
@@ -35,6 +36,7 @@
#include "vcsmanager.h"
#include <app/app_version.h>
#include <coreplugin.h>
#include <utils/checkablemessagebox.h>
#include <utils/consoleprocess.h>
#include <utils/environment.h>
@@ -50,9 +52,28 @@
using namespace Utils;
static const char crashReportingEnabledKey[] = "CrashReportingEnabled";
static const char showCrashButtonKey[] = "ShowCrashButton";
namespace Core {
namespace Internal {
// TODO: move to somewhere in Utils
static QString formatSize(qint64 size)
{
QStringList units {QObject::tr("Bytes"), QObject::tr("KB"), QObject::tr("MB"),
QObject::tr("GB"), QObject::tr("TB")};
double outputSize = size;
int i;
for (i = 0; i < units.size() - 1; ++i) {
if (outputSize < 1024)
break;
outputSize /= 1024;
}
return i == 0 ? QString("%0 %1").arg(outputSize).arg(units[i]) // Bytes
: QString("%0 %1").arg(outputSize, 0, 'f', 2).arg(units[i]); // KB, MB, GB, TB
}
class SystemSettingsWidget : public IOptionsPageWidget
{
Q_DECLARE_TR_FUNCTIONS(Core::Internal::SystemSettingsWidget)
@@ -113,6 +134,46 @@ public:
m_ui.maxRecentFilesSpinBox->setMinimum(1);
m_ui.maxRecentFilesSpinBox->setMaximum(99);
m_ui.maxRecentFilesSpinBox->setValue(EditorManagerPrivate::maxRecentFiles());
#ifdef ENABLE_CRASHPAD
if (ICore::settings()->value(showCrashButtonKey).toBool()) {
auto crashButton = new QPushButton("CRASH!!!");
crashButton->show();
connect(crashButton, &QPushButton::clicked, []() {
// do a real crash
volatile int* a = reinterpret_cast<volatile int *>(NULL); *a = 1;
});
}
m_ui.enableCrashReportingCheckBox->setChecked(
ICore::settings()->value(crashReportingEnabledKey).toBool());
connect(m_ui.helpCrashReportingButton, &QAbstractButton::clicked, this, [this] {
showHelpDialog(tr("Crash Reporting"), CorePlugin::msgCrashpadInformation());
});
connect(m_ui.enableCrashReportingCheckBox,
QOverload<int>::of(&QCheckBox::stateChanged), this, [this] {
const QString restartText = tr("The change will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
if (restartDialog.result() == QDialog::Accepted)
apply();
});
updateClearCrashWidgets();
connect(m_ui.clearCrashReportsButton, &QPushButton::clicked, this, [&] {
QDir crashReportsDir(ICore::crashReportsPath());
crashReportsDir.setFilter(QDir::Files);
const QStringList crashFiles = crashReportsDir.entryList();
for (QString file : crashFiles)
crashReportsDir.remove(file);
updateClearCrashWidgets();
});
#else
m_ui.enableCrashReportingCheckBox->setVisible(false);
m_ui.helpCrashReportingButton->setVisible(false);
m_ui.clearCrashReportsButton->setVisible(false);
m_ui.crashReportsSizeText->setVisible(false);
#endif
m_ui.askBeforeExitCheckBox->setChecked(
static_cast<Core::Internal::MainWindow *>(ICore::mainWindow())->askConfirmationBeforeExit());
@@ -182,8 +243,9 @@ private:
void updateTerminalUi(const Utils::TerminalCommand &term);
void updatePath();
void updateEnvironmentChangesLabel();
void updateClearCrashWidgets();
void variableHelpDialogCreator(const QString &helpText);
void showHelpDialog(const QString &title, const QString &helpText);
Ui::SystemSettings m_ui;
QPointer<QMessageBox> m_dialog;
EnvironmentItems m_environmentChanges;
@@ -211,6 +273,11 @@ void SystemSettingsWidget::apply()
m_ui.warnBeforeOpeningBigFiles->isChecked());
EditorManagerPrivate::setBigFileSizeLimit(m_ui.bigFilesLimitSpinBox->value());
EditorManagerPrivate::setMaxRecentFiles(m_ui.maxRecentFilesSpinBox->value());
#ifdef ENABLE_CRASHPAD
ICore::settings()->setValue(crashReportingEnabledKey,
m_ui.enableCrashReportingCheckBox->isChecked());
#endif
static_cast<Core::Internal::MainWindow *>(ICore::mainWindow())->setAskConfirmationBeforeExit(
m_ui.askBeforeExitCheckBox->isChecked());
@@ -263,9 +330,12 @@ void SystemSettingsWidget::updateEnvironmentChangesLabel()
: shortSummary);
}
void SystemSettingsWidget::variableHelpDialogCreator(const QString &helpText)
void SystemSettingsWidget::showHelpDialog(const QString &title, const QString &helpText)
{
if (m_dialog) {
if (m_dialog->windowTitle() != title)
m_dialog->setText(helpText);
if (m_dialog->text() != helpText)
m_dialog->setText(helpText);
@@ -273,20 +343,31 @@ void SystemSettingsWidget::variableHelpDialogCreator(const QString &helpText)
ICore::raiseWindow(m_dialog);
return;
}
QMessageBox *mb = new QMessageBox(QMessageBox::Information,
tr("Variables"),
helpText,
QMessageBox::Close,
this);
auto mb = new QMessageBox(QMessageBox::Information, title, helpText, QMessageBox::Close, this);
mb->setWindowModality(Qt::NonModal);
m_dialog = mb;
mb->show();
}
#ifdef ENABLE_CRASHPAD
void SystemSettingsWidget::updateClearCrashWidgets()
{
QDir crashReportsDir(ICore::crashReportsPath());
crashReportsDir.setFilter(QDir::Files);
qint64 size = 0;
const QStringList crashFiles = crashReportsDir.entryList();
for (QString file : crashFiles)
size += QFileInfo(crashReportsDir, file).size();
m_ui.clearCrashReportsButton->setEnabled(!crashFiles.isEmpty());
m_ui.crashReportsSizeText->setText(formatSize(size));
}
#endif
void SystemSettingsWidget::showHelpForFileBrowser()
{
if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost())
variableHelpDialogCreator(UnixUtils::fileBrowserHelpText());
showHelpDialog(tr("Variables"), UnixUtils::fileBrowserHelpText());
}
SystemSettings::SystemSettings()

View File

@@ -309,6 +309,24 @@
</item>
</layout>
</item>
<item row="12" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QPushButton" name="clearCrashReportsButton">
<property name="text">
<string>Clear local crash reports</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="crashReportsSizeText">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1" colspan="2">
<widget class="QWidget" name="externalFileBrowserWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9">
@@ -455,6 +473,40 @@
</layout>
</widget>
</item>
<item row="11" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QCheckBox" name="enableCrashReportingCheckBox">
<property name="toolTip">
<string>Allow crashes to be automatically reported. Collected reports are used for the sole purpose of fixing bugs.</string>
</property>
<property name="text">
<string>Enable crash reporting</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="helpCrashReportingButton">
<property name="text">
<string>?</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>
</layout>
</item>
</layout>
</widget>
</item>

View File

@@ -38,10 +38,31 @@ Image {
signal goNext
signal closeClicked
signal configureClicked
property alias doNotShowAgain: do_not_show_checkBox.checked
property bool loadingPlugins: true
// called from C++
function onPluginInitialized(crashReportingEnabled: bool, crashReportingOn: bool)
{
loadingPlugins = false
if (crashReportingEnabled) {
var configureButton = "<a href='#' style='text-decoration:none;color:#ffff00'>"
+ qsTr("[Configure]") + "</a>";
var settingPath = Qt.platform.os === "osx"
? qsTr("Qt Creator > Preferences > Environment > System")
: qsTr("Tools > Options > Environment > System")
var strOn = qsTr("Qt Design Studio collects crash reports for the sole purpose of fixing bugs. "
+ "You can disable this feature under %1. %2").arg(settingPath).arg(configureButton)
var strOff = qsTr("Qt Design Studio can collect crash reports for the sole purpose of fixing bugs. "
+ "You can enable this feature under %1. %2").arg(settingPath).arg(configureButton)
crash_reporting_text.text = crashReportingOn ? strOn : strOff;
}
}
Image {
id: logo
x: 14
@@ -104,7 +125,7 @@ Image {
Text {
id: marketing_1
x: 16
y: 302
y: 252
width: 355
height: 31
color: "#ffffff"
@@ -118,7 +139,7 @@ Image {
Text {
id: marketing_2
x: 16
y: 323
y: 273
width: 311
height: 31
color: "#ffffff"
@@ -132,7 +153,7 @@ Image {
Text {
id: marketing_3
x: 16
y: 344
y: 294
width: 311
height: 31
color: "#ffffff"
@@ -143,6 +164,26 @@ Image {
font.wordSpacing: 0
}
Text {
id: crash_reporting_text
color: "#ffffff"
textFormat: Text.RichText
x: 16
y: 330
width: 311
wrapMode: Text.WordWrap
font.family: StudioFonts.titilliumWeb_light
font.pixelSize: 12
font.wordSpacing: 0
onLinkActivated: welcome_splash.configureClicked()
MouseArea { // show hand cursor on link hover
anchors.fill: parent
acceptedButtons: Qt.NoButton // don't eat clicks on the Text
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Dof_Effect {
id: dof_Effect
x: 358
@@ -192,10 +233,9 @@ Image {
scale: 0.5
}
RowLayout {
x: 16
y: 254
y: 330
visible: welcome_splash.loadingPlugins

View File

@@ -32,9 +32,14 @@ Item {
signal closeClicked
signal checkBoxToggled
signal configureClicked
property alias doNotShowAgain: welcome_splash.doNotShowAgain
property alias loadingPlugins: welcome_splash.loadingPlugins
function onPluginInitialized(crashReportingEnabled: bool, crashReportingOn: bool)
{
welcome_splash.onPluginInitialized(crashReportingEnabled, crashReportingOn);
}
Welcome_splash {
id: welcome_splash
@@ -42,5 +47,6 @@ Item {
y: 0
antialiasing: true
onCloseClicked: root.closeClicked()
onConfigureClicked: root.configureClicked()
}
}

View File

@@ -36,12 +36,12 @@
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectmanager.h>
#include <utils/checkablemessagebox.h>
#include <utils/icon.h>
#include <utils/infobar.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
@@ -264,6 +264,18 @@ void StudioWelcomePlugin::closeSplashScreen()
}
}
void StudioWelcomePlugin::showSystemSettings()
{
Core::ICore::infoBar()->removeInfo("WarnCrashReporting");
Core::ICore::infoBar()->globallySuppressInfo("WarnCrashReporting");
// pause remove splash timer while settings dialog is open otherwise splash crashes upon removal
int splashAutoCloseRemainingTime = m_removeSplashTimer.remainingTime(); // milliseconds
m_removeSplashTimer.stop();
Core::ICore::showOptionsDialog(Core::Constants::SETTINGS_ID_SYSTEM);
m_removeSplashTimer.start(splashAutoCloseRemainingTime);
}
StudioWelcomePlugin::~StudioWelcomePlugin()
{
delete m_welcomeMode;
@@ -284,6 +296,9 @@ bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *erro
QFont systemFont("Titillium Web", QApplication::font().pointSize());
QApplication::setFont(systemFont);
m_removeSplashTimer.setSingleShot(true);
m_removeSplashTimer.setInterval(15000);
connect(&m_removeSplashTimer, &QTimer::timeout, this, [this] { closeSplashScreen(); });
return true;
}
@@ -292,7 +307,7 @@ void StudioWelcomePlugin::extensionsInitialized()
Core::ModeManager::activateMode(m_welcomeMode->id());
if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] (){
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
s_view = new QQuickWidget(Core::ICore::dialogParent());
s_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
s_view->setWindowFlag(Qt::SplashScreen, true);
@@ -313,11 +328,12 @@ void StudioWelcomePlugin::extensionsInitialized()
return);
connect(s_view->rootObject(), SIGNAL(closeClicked()), this, SLOT(closeSplashScreen()));
connect(s_view->rootObject(), SIGNAL(configureClicked()), this, SLOT(showSystemSettings()));
s_view->show();
s_view->raise();
QTimer::singleShot(15000, [this](){ closeSplashScreen(); });
m_removeSplashTimer.start();
});
}
}
@@ -329,7 +345,17 @@ bool StudioWelcomePlugin::delayedInitialize()
QTC_ASSERT(s_view->rootObject() , return true);
s_view->rootObject()->setProperty("loadingPlugins", false);
#ifdef ENABLE_CRASHPAD
const bool crashReportingEnabled = true;
const bool crashReportingOn = Core::ICore::settings()->value("CrashReportingEnabled", false).toBool();
#else
const bool crashReportingEnabled = false;
const bool crashReportingOn = false;
#endif
QMetaObject::invokeMethod(s_view->rootObject(), "onPluginInitialized",
Q_ARG(bool, crashReportingEnabled), Q_ARG(bool, crashReportingOn));
return false;
}

View File

@@ -27,6 +27,8 @@
#include <extensionsystem/iplugin.h>
#include <QTimer>
namespace StudioWelcome {
namespace Internal {
@@ -37,6 +39,7 @@ class StudioWelcomePlugin final : public ExtensionSystem::IPlugin
public slots:
void closeSplashScreen();
void showSystemSettings();
public:
~StudioWelcomePlugin() final;
@@ -47,6 +50,7 @@ public:
private:
class WelcomeMode *m_welcomeMode = nullptr;
QTimer m_removeSplashTimer;
};
} // namespace Internal

View File

@@ -207,3 +207,25 @@ extend_qtc_executable(qml2puppet
DEPENDS QtCreator::multilanguage-support
FEATURE_INFO "multilanguage-support in qml2puppet"
)
# Crashpad
# only windows requires separate crashpad client per process until client->SetHandlerIPCPipe()
# is implemented (check the TODO inside startCrashpad())
if (CRASHPAD_BACKEND_URL
AND CRASHPAD_SRC
AND EXISTS "${CRASHPAD_SRC}"
AND CRASHPAD_BUILD
AND EXISTS "${CRASHPAD_BUILD}"
AND WIN32)
target_compile_definitions(qml2puppet PRIVATE
CRASHPAD_BACKEND_URL="${CRASHPAD_BACKEND_URL}"
ENABLE_CRASHPAD)
target_include_directories(qml2puppet PRIVATE
"${CRASHPAD_SRC}"
"${CRASHPAD_SRC}/third_party/mini_chromium/mini_chromium")
target_link_libraries(qml2puppet PUBLIC ${CRASHPAD_BUILD}/obj/third_party/mini_chromium/mini_chromium/base/base.lib
${CRASHPAD_BUILD}/obj/util/util.lib
${CRASHPAD_BUILD}/obj/client/client.lib
advapi32)
endif()