Workaround for bug in Qt 5 that causes crashes if QDesktopServices is used before constructing a QApplication

This commit is contained in:
Kovid Goyal 2014-08-19 11:06:18 +05:30
parent 17f7b8a14f
commit 796cba4b69
3 changed files with 19 additions and 5 deletions

View File

@ -1032,6 +1032,9 @@ class SanitizeLibraryPath(object):
os.environ[var] = orig os.environ[var] = orig
def open_url(qurl): def open_url(qurl):
# Qt 5 requires QApplication to be constructed before trying to use
# QDesktopServices::openUrl()
ensure_app()
if isinstance(qurl, basestring): if isinstance(qurl, basestring):
qurl = QUrl(qurl) qurl = QUrl(qurl)
with SanitizeLibraryPath(): with SanitizeLibraryPath():
@ -1057,6 +1060,14 @@ def open_local_file(path):
url = QUrl.fromLocalFile(path) url = QUrl.fromLocalFile(path)
open_url(url) open_url(url)
def ensure_app():
global _store_app
if _store_app is None and QApplication.instance() is None:
args = sys.argv[:1]
if islinux or isbsd:
args += ['-platformpluginpath', sys.extensions_location, '-platform', 'headless']
_store_app = QApplication(args)
def must_use_qt(): def must_use_qt():
''' This function should be called if you want to use Qt for some non-GUI ''' This function should be called if you want to use Qt for some non-GUI
task like rendering HTML/SVG or using a headless browser. It will raise a task like rendering HTML/SVG or using a headless browser. It will raise a
@ -1064,11 +1075,7 @@ def must_use_qt():
thread is not the main GUI thread. On linux, it uses a special QPA headless thread is not the main GUI thread. On linux, it uses a special QPA headless
plugin, so that the X server does not need to be running. ''' plugin, so that the X server does not need to be running. '''
global gui_thread, _store_app global gui_thread, _store_app
if _store_app is None and QApplication.instance() is None: ensure_app()
args = sys.argv[:1]
if islinux or isbsd:
args += ['-platformpluginpath', sys.extensions_location, '-platform', 'headless']
_store_app = QApplication(args)
if gui_thread is None: if gui_thread is None:
gui_thread = QThread.currentThread() gui_thread = QThread.currentThread()
if gui_thread is not QThread.currentThread(): if gui_thread is not QThread.currentThread():

View File

@ -25,6 +25,8 @@ HeadlessIntegration::HeadlessIntegration(const QStringList &parameters)
screenAdded(mPrimaryScreen); screenAdded(mPrimaryScreen);
m_fontDatabase.reset(new QFontconfigDatabase()); m_fontDatabase.reset(new QFontconfigDatabase());
platform_services.reset(new QGenericUnixServices());
} }
HeadlessIntegration::~HeadlessIntegration() HeadlessIntegration::~HeadlessIntegration()

View File

@ -2,6 +2,8 @@
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include <qpa/qplatformscreen.h> #include <qpa/qplatformscreen.h>
#include <qpa/qplatformservices.h>
#include <QtPlatformSupport/private/qgenericunixservices_p.h>
#include <QScopedPointer> #include <QScopedPointer>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -41,8 +43,11 @@ public:
static HeadlessIntegration *instance(); static HeadlessIntegration *instance();
virtual QPlatformServices *services() const { return platform_services.data(); }
private: private:
QScopedPointer<QPlatformFontDatabase> m_fontDatabase; QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
QScopedPointer<QPlatformServices> platform_services;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE