forked from qt-creator/qt-creator
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:
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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";
|
||||
|
@@ -99,6 +99,7 @@ public:
|
||||
static QString cacheResourcePath();
|
||||
static QString installerResourcePath();
|
||||
static QString libexecPath();
|
||||
static QString crashReportsPath();
|
||||
|
||||
static QString versionString();
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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()
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user