aboutsummaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2023-12-04 14:44:03 +0100
committerEike Ziller <eike.ziller@qt.io>2023-12-05 12:04:45 +0000
commita6a95420b6be814096394b004268219727beb354 (patch)
tree6a4c0120c7e317674beef6d0adb447a903100458 /src/app
parent9a364811de9e53e3df544ac963bbeafa0d58380c (diff)
Main: Show a GUI message if platform plugin fails to load
If the Qt platform plugin fails to load, most famously xcb on systems that do not have libxcb-cursor0 installed, the interesting messages are only written to a terminal, and not visible when running Qt Creator from e.g. the installer or dock. Temporarily install a special Qt message handler that scribbles along the qWarnings and qFatals while creating the QGuiApplication, and make it output the messages via xmessage in case a qFatal is received (and xmessage is available). On macOS show a dialog with osascript. Windows already gets a dialog from Qt proper. Also add the explicit message about (lib)xcb-cursor0 for Qt versions that do not have it yet. Fixes: QTCREATORBUG-30004 Task-number: QTBUG-108796 Task-number: QTCREATORBUG-29873 Change-Id: I5e5dafb398db6a72178413c8b883325c56d9a016 Reviewed-by: Cristian Adam <cristian.adam@qt.io>
Diffstat (limited to 'src/app')
-rw-r--r--src/app/main.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 036d169c06..819e0f1189 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -477,6 +477,53 @@ bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
}
#endif
+class ShowInGuiHandler
+{
+public:
+ ShowInGuiHandler()
+ {
+ instance = this;
+ oldHandler = qInstallMessageHandler(log);
+ }
+ ~ShowInGuiHandler() { qInstallMessageHandler(oldHandler); };
+
+private:
+ static void log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+ {
+ instance->messages += msg;
+ if (type == QtFatalMsg) {
+ // Show some kind of GUI with collected messages before exiting.
+ // For Windows, Qt already uses a dialog.
+ if (Utils::HostOsInfo::isLinuxHost()) {
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) && QT_VERSION < QT_VERSION_CHECK(6, 5, 3)) \
+ || (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) && QT_VERSION < QT_VERSION_CHECK(6, 6, 1))
+ // Information about potentially missing libxcb-cursor0 is printed by Qt since Qt 6.5.3 and Qt 6.6.1
+ // Add it manually for other versions >= 6.5.0
+ instance->messages.prepend("From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to "
+ "load the Qt xcb platform plugin.");
+#endif
+ if (QFile::exists("/usr/bin/xmessage"))
+ QProcess::startDetached("/usr/bin/xmessage", {instance->messages.join("\n")});
+ } else if (Utils::HostOsInfo::isMacHost()) {
+ QProcess::startDetached("/usr/bin/osascript",
+ {"-e",
+ "display dialog \""
+ + instance->messages.join("\n").replace("\"", "\\\"")
+ + "\" buttons \"OK\" with title \""
+ + Core::Constants::IDE_DISPLAY_NAME
+ + " Failed to Start\""});
+ }
+ }
+ instance->oldHandler(type, context, msg);
+ };
+
+ static ShowInGuiHandler *instance;
+ QStringList messages;
+ QtMessageHandler oldHandler = nullptr;
+};
+
+ShowInGuiHandler *ShowInGuiHandler::instance = nullptr;
+
int main(int argc, char **argv)
{
Restarter restarter(argc, argv);
@@ -590,9 +637,13 @@ int main(int argc, char **argv)
int numberOfArguments = static_cast<int>(options.appArguments.size());
+ // create a custom Qt message handler that shows messages in a bare bones UI
+ // if creation of the QGuiApplication fails.
+ auto handler = std::make_unique<ShowInGuiHandler>();
std::unique_ptr<SharedTools::QtSingleApplication>
appPtr(SharedTools::createApplication(QLatin1String(Core::Constants::IDE_DISPLAY_NAME),
numberOfArguments, options.appArguments.data()));
+ handler.reset();
SharedTools::QtSingleApplication &app = *appPtr;
QCoreApplication::setApplicationName(Core::Constants::IDE_CASED_ID);
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));