Prevent static functions of Q[Gui]Application from crashing if there is no instance.

Add tests.

Task-number: QTBUG-44499
Change-Id: I160b089ad3f23ab71a87519e50f8a2ef5d2a4a6f
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
Friedemann Kleint 2015-02-24 09:35:56 +01:00
parent 4e966497ce
commit 175b12beba
4 changed files with 87 additions and 0 deletions

View File

@ -105,6 +105,14 @@
QT_BEGIN_NAMESPACE
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
if (Q_LIKELY(QCoreApplication::instance())) { \
} else { \
qWarning("Must construct a QGuiApplication first."); \
return __VA_ARGS__; \
}
Q_GUI_EXPORT bool qt_is_gui_used = true;
Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
@ -648,6 +656,7 @@ QString QGuiApplication::applicationDisplayName()
*/
QWindow *QGuiApplication::modalWindow()
{
CHECK_QAPP_INSTANCE(Q_NULLPTR)
if (QGuiApplicationPrivate::self->modalWindowList.isEmpty())
return 0;
return QGuiApplicationPrivate::self->modalWindowList.first();
@ -1430,6 +1439,7 @@ Qt::KeyboardModifiers QGuiApplication::keyboardModifiers()
*/
Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
{
CHECK_QAPP_INSTANCE(Qt::KeyboardModifiers(0))
QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
return pi->queryKeyboardModifiers();
}
@ -3167,6 +3177,7 @@ Qt::LayoutDirection QGuiApplication::layoutDirection()
#ifndef QT_NO_CURSOR
QCursor *QGuiApplication::overrideCursor()
{
CHECK_QAPP_INSTANCE(Q_NULLPTR)
return qGuiApp->d_func()->cursor_list.isEmpty() ? 0 : &qGuiApp->d_func()->cursor_list.first();
}
@ -3180,6 +3191,7 @@ QCursor *QGuiApplication::overrideCursor()
*/
void QGuiApplication::changeOverrideCursor(const QCursor &cursor)
{
CHECK_QAPP_INSTANCE()
if (qGuiApp->d_func()->cursor_list.isEmpty())
return;
qGuiApp->d_func()->cursor_list.removeFirst();
@ -3254,6 +3266,7 @@ static inline void applyWindowCursor(const QList<QWindow *> &l)
*/
void QGuiApplication::setOverrideCursor(const QCursor &cursor)
{
CHECK_QAPP_INSTANCE()
qGuiApp->d_func()->cursor_list.prepend(cursor);
applyCursor(QGuiApplicationPrivate::window_list, cursor);
}
@ -3271,6 +3284,7 @@ void QGuiApplication::setOverrideCursor(const QCursor &cursor)
*/
void QGuiApplication::restoreOverrideCursor()
{
CHECK_QAPP_INSTANCE()
if (qGuiApp->d_func()->cursor_list.isEmpty())
return;
qGuiApp->d_func()->cursor_list.removeFirst();
@ -3338,6 +3352,7 @@ bool QGuiApplication::desktopSettingsAware()
*/
QInputMethod *QGuiApplication::inputMethod()
{
CHECK_QAPP_INSTANCE(Q_NULLPTR)
if (!qGuiApp->d_func()->inputMethod)
qGuiApp->d_func()->inputMethod = new QInputMethod();
return qGuiApp->d_func()->inputMethod;

View File

@ -117,6 +117,14 @@ static void initResources()
QT_BEGIN_NAMESPACE
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
if (Q_LIKELY(QCoreApplication::instance())) { \
} else { \
qWarning("Must construct a QApplication first."); \
return __VA_ARGS__; \
}
Q_CORE_EXPORT void qt_call_post_routines();
QApplicationPrivate *QApplicationPrivate::self = 0;
@ -2855,6 +2863,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
*/
QDesktopWidget *QApplication::desktop()
{
CHECK_QAPP_INSTANCE(Q_NULLPTR)
if (!qt_desktopWidget || // not created yet
!(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away
qt_desktopWidget = new QDesktopWidget();
@ -4110,6 +4119,7 @@ void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
*/
bool QApplication::isEffectEnabled(Qt::UIEffect effect)
{
CHECK_QAPP_INSTANCE(false)
return QColormap::instance().depth() >= 16
&& (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
&& (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));

View File

@ -77,6 +77,8 @@ private slots:
void layoutDirection();
void globalShareContext();
void staticFunctions();
void settableStyleHints_data();
void settableStyleHints(); // Needs to run last as it changes style hints.
};
@ -966,6 +968,42 @@ void tst_QGuiApplication::globalShareContext()
#endif
}
// Test that static functions do not crash if there is no application instance.
void tst_QGuiApplication::staticFunctions()
{
QGuiApplication::setApplicationDisplayName(QString());
QGuiApplication::applicationDisplayName();
QGuiApplication::allWindows();
QGuiApplication::topLevelWindows();
QGuiApplication::topLevelAt(QPoint(0, 0));
QGuiApplication::setWindowIcon(QIcon());
QGuiApplication::windowIcon();
QGuiApplication::platformName();
QGuiApplication::modalWindow();
QGuiApplication::focusWindow();
QGuiApplication::focusObject();
QGuiApplication::primaryScreen();
QGuiApplication::screens();
QGuiApplication::overrideCursor();
QGuiApplication::setOverrideCursor(QCursor());
QGuiApplication::changeOverrideCursor(QCursor());
QGuiApplication::restoreOverrideCursor();
QGuiApplication::keyboardModifiers();
QGuiApplication::queryKeyboardModifiers();
QGuiApplication::mouseButtons();
QGuiApplication::setLayoutDirection(Qt::LeftToRight);
QGuiApplication::layoutDirection();
QGuiApplication::styleHints();
QGuiApplication::setDesktopSettingsAware(true);
QGuiApplication::desktopSettingsAware();
QGuiApplication::inputMethod();
QGuiApplication::platformNativeInterface();
QGuiApplication::platformFunction(QByteArrayLiteral("bla"));
QGuiApplication::setQuitOnLastWindowClosed(true);
QGuiApplication::quitOnLastWindowClosed();
QGuiApplication::applicationState();
}
void tst_QGuiApplication::settableStyleHints_data()
{
QTest::addColumn<bool>("appInstance");

View File

@ -172,6 +172,8 @@ private slots:
void abortQuitOnShow();
void staticFunctions();
void settableStyleHints_data();
void settableStyleHints(); // Needs to run last as it changes style hints.
};
@ -2299,6 +2301,28 @@ void tst_QApplication::abortQuitOnShow()
QCOMPARE(app.exec(), 1);
}
// Test that static functions do not crash if there is no application instance.
void tst_QApplication::staticFunctions()
{
QApplication::setStyle(QStringLiteral("blub"));
QApplication::colorSpec();
QApplication::setColorSpec(42);
QApplication::allWidgets();
QApplication::topLevelWidgets();
QApplication::desktop();
QApplication::activePopupWidget();
QApplication::activeModalWidget();
QApplication::focusWidget();
QApplication::activeWindow();
QApplication::setActiveWindow(Q_NULLPTR);
QApplication::widgetAt(QPoint(0, 0));
QApplication::topLevelAt(QPoint(0, 0));
QApplication::setGlobalStrut(QSize(0, 0));
QApplication::globalStrut();
QApplication::isEffectEnabled(Qt::UI_General);
QApplication::setEffectEnabled(Qt::UI_General, false);
}
void tst_QApplication::settableStyleHints_data()
{
QTest::addColumn<bool>("appInstance");