forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -477,6 +477,53 @@ bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Restarter restarter(argc, argv);
|
Restarter restarter(argc, argv);
|
||||||
@@ -590,9 +637,13 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
int numberOfArguments = static_cast<int>(options.appArguments.size());
|
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>
|
std::unique_ptr<SharedTools::QtSingleApplication>
|
||||||
appPtr(SharedTools::createApplication(QLatin1String(Core::Constants::IDE_DISPLAY_NAME),
|
appPtr(SharedTools::createApplication(QLatin1String(Core::Constants::IDE_DISPLAY_NAME),
|
||||||
numberOfArguments, options.appArguments.data()));
|
numberOfArguments, options.appArguments.data()));
|
||||||
|
handler.reset();
|
||||||
SharedTools::QtSingleApplication &app = *appPtr;
|
SharedTools::QtSingleApplication &app = *appPtr;
|
||||||
QCoreApplication::setApplicationName(Core::Constants::IDE_CASED_ID);
|
QCoreApplication::setApplicationName(Core::Constants::IDE_CASED_ID);
|
||||||
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
|
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
|
||||||
|
Reference in New Issue
Block a user