diff options
Diffstat (limited to 'src')
366 files changed, 13545 insertions, 3199 deletions
diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp index 59fd5c7..9f651d6 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.cpp +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -216,14 +216,14 @@ void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescripti { IFACE; iface->interfaceCall(AddonInterface::AudioChannelInterface, - AddonInterface::setCurrentAudioChannel, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentAudioChannel, QList<QVariant>() << QVariant::fromValue(stream)); } void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &stream) { IFACE; iface->interfaceCall(AddonInterface::SubtitleInterface, - AddonInterface::setCurrentSubtitle, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentSubtitle, QList<QVariant>() << QVariant::fromValue(stream)); } #undef IFACE diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h index f28ecaa..f25b15e 100644 --- a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h +++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h @@ -54,7 +54,7 @@ class QSettingsGroup template<typename T> inline T value(const QString &key, const T &def) const { - return qvariant_cast<T>(value(key, qVariantFromValue(def))); + return qvariant_cast<T>(value(key, QVariant::fromValue(def))); } inline QVariant value(const QString &key, const QVariant &def) const @@ -66,7 +66,7 @@ class QSettingsGroup inline void setValue(const QString &key, const T &value) { Q_ASSERT(m_mutableSettings); - m_mutableSettings->setValue(m_group + key, qVariantFromValue(value)); + m_mutableSettings->setValue(m_group + key, QVariant::fromValue(value)); } inline void removeEntry(const QString &key) diff --git a/src/3rdparty/phonon/qt7/videowidget.mm b/src/3rdparty/phonon/qt7/videowidget.mm index 736dcdf..c281e16 100644 --- a/src/3rdparty/phonon/qt7/videowidget.mm +++ b/src/3rdparty/phonon/qt7/videowidget.mm @@ -278,7 +278,7 @@ public: glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, GLsizei(w), GLsizei(h)); - gluOrtho2D(0, GLsizei(w), 0, GLsizei(h)); + glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1); updateGL(); } diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp index 2212f58..7f5d37d 100644 --- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp @@ -567,7 +567,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qstring.mid(lastSlash + 1).contains(QLatin1Char('i'))) realRe.setCaseSensitivity(Qt::CaseInsensitive); - ret = qVariantFromValue(realRe); + ret = QVariant::fromValue(realRe); dist = 0; } else { qConvDebug() << "couldn't parse a JS regexp"; @@ -578,7 +578,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type QRegExp re(qstring); if (re.isValid()) { - ret = qVariantFromValue(re); + ret = QVariant::fromValue(re); dist = 10; } } @@ -590,7 +590,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue(qtinst->getObject()); + ret = QVariant::fromValue(qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -601,7 +601,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type } } else if (type == Null) { QObject* nullobj = 0; - ret = qVariantFromValue(nullobj); + ret = QVariant::fromValue(nullobj); dist = 0; } else { qConvDebug() << "previous type was not an object:" << type; @@ -614,7 +614,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue((void *)qtinst->getObject()); + ret = QVariant::fromValue((void *)qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -624,7 +624,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type qConvDebug() << "wasn't a qtinstance"; } } else if (type == Null) { - ret = qVariantFromValue((void*)0); + ret = QVariant::fromValue((void*)0); dist = 0; } else if (type == Number) { // I don't think that converting a double to a pointer is a wise diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 88c7a1c..9de5c08 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -101,7 +101,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) // Make sure we get updates for each frame m_videoWidget->installEventFilter(this); - foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget)) + foreach (QWidget* widget, m_videoWidget->findChildren<QWidget*>()) widget->installEventFilter(this); connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 5db94a8..5004b67 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -185,7 +185,7 @@ void MediaPlayerPrivate::load(const String& url) // Don't set the header if there are no cookies. // This prevents a warning from being emitted. if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); // Set the refferer, but not when requesting insecure content from a secure page QUrl documentUrl = QUrl(QString(document->documentURI())); diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index e584f97..dcae35f 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -306,7 +306,7 @@ public: } Q_INVOKABLE QObjectList myInvokableWithQObjectListArg(const QObjectList &lst) { m_qtFunctionInvoked = 14; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QVariant myInvokableWithVariantArg(const QVariant &v) { @@ -321,38 +321,38 @@ public: } Q_INVOKABLE QList<int> myInvokableWithListOfIntArg(const QList<int> &lst) { m_qtFunctionInvoked = 17; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QObject* myInvokableWithQObjectStarArg(QObject* obj) { m_qtFunctionInvoked = 18; - m_actuals << qVariantFromValue(obj); + m_actuals << QVariant::fromValue(obj); return obj; } Q_INVOKABLE QBrush myInvokableWithQBrushArg(const QBrush &brush) { m_qtFunctionInvoked = 19; - m_actuals << qVariantFromValue(brush); + m_actuals << QVariant::fromValue(brush); return brush; } Q_INVOKABLE void myInvokableWithBrushStyleArg(Qt::BrushStyle style) { m_qtFunctionInvoked = 43; - m_actuals << qVariantFromValue(style); + m_actuals << QVariant::fromValue(style); } Q_INVOKABLE void myInvokableWithVoidStarArg(void* arg) { m_qtFunctionInvoked = 44; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(int arg) { m_qtFunctionInvoked = 45; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(uint arg) { m_qtFunctionInvoked = 46; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithDefaultArgs(int arg1, const QString &arg2 = "") { m_qtFunctionInvoked = 47; - m_actuals << qVariantFromValue(arg1) << qVariantFromValue(arg2); + m_actuals << QVariant::fromValue(arg1) << qVariantFromValue(arg2); } Q_INVOKABLE QObject& myInvokableReturningRef() { m_qtFunctionInvoked = 48; @@ -364,11 +364,11 @@ public: } Q_INVOKABLE void myInvokableWithPointArg(const QPoint &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 50; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithPointArg(const QPointF &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 51; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithBoolArg(bool arg) { m_qtFunctionInvoked = 52; @@ -416,7 +416,7 @@ public Q_SLOTS: } void myOverloadedSlot(QObject* arg) { m_qtFunctionInvoked = 41; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } void myOverloadedSlot(bool arg) { m_qtFunctionInvoked = 25; @@ -818,7 +818,7 @@ void tst_QWebFrame::getSetStaticProperty() QCOMPARE(evalJS("myObject.variantProperty === 'bar'"), sTrue); m_myObject->setVariantProperty(42); QCOMPARE(evalJS("myObject.variantProperty === 42"), sTrue); - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); //XFAIL // QCOMPARE(evalJS("typeof myObject.variantProperty"), sVariant); @@ -1240,7 +1240,7 @@ void tst_QWebFrame::callQtInvokable() /* XFAIL - variant support m_myObject->resetQtFunctionInvoked(); { - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); QVariant ret = evalJS("myObject.myInvokableWithVariantArg(myObject.variantProperty)"); QVERIFY(ret.isVariant()); QCOMPARE(m_myObject->qtFunctionInvoked(), 15); diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index 7692749..806e2b1 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -3540,7 +3540,7 @@ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v) proptype = 0; } else if (t == QVariant::UserType) { qvar = QVariant(qRegisterMetaType<void*>(prop.typeName()), (void**)v[0]); -// qVariantSetValue(qvar, *(void**)v[0], prop.typeName()); +// qvar.setValue(*(void**)v[0], prop.typeName()); } else { proptype = d->metaObject()->propertyType(propname); qvar = QVariant(t, v[0]); @@ -3628,9 +3628,9 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) if (!qvar.isValid()) { if (type == "IDispatch*") - qVariantSetValue(qvar, *(IDispatch**)v[p+1]); + qvar.setValue(*(IDispatch**)v[p+1]); else if (type == "IUnknown*") - qVariantSetValue(qvar, *(IUnknown**)v[p+1]); + qvar.setValue(*(IUnknown**)v[p+1]); else if (type == "QVariant") qvar = *(QVariant*)v[p + 1]; else if (mo->indexOfEnumerator(type) != -1) @@ -4395,15 +4395,15 @@ QVariant QAxBase::asVariant() const QByteArray cn(className()); if (cn == "QAxObject" || cn == "QAxWidget" || cn == "QAxBase") { if (d->dispatch()) - qVariantSetValue(qvar, d->dispatch()); + qvar.setValue(d->dispatch()); else if (d->ptr) - qVariantSetValue(qvar, d->ptr); + qvar.setValue(d->ptr); } else { cn = cn.mid(cn.lastIndexOf(':') + 1); QObject *object = qObject(); if (QMetaType::type(cn)) qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object); -// qVariantSetValue(qvar, qObject(), cn + '*'); +// qvar.setValue(qObject(), cn + '*'); } return qvar; diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index 7afce5b..d3f736b 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -1163,7 +1163,7 @@ HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPW AX_DEBUG(QAxClientSite::InsertMenus); QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; @@ -1309,7 +1309,7 @@ HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND m_menuOwner = hwndActiveObject; QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index 7728e50..2512f05 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -285,7 +285,7 @@ HRESULT UpdateRegistry(BOOL bRegister) |OLEMISC_RECOMPOSEONRESIZE; if (!control) olemisc |= OLEMISC_INVISIBLEATRUNTIME; - else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe) + else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe) olemisc |= OLEMISC_WANTSTOMENUMERGE; settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class")); diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index ca16b39..32e2cf2 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -1313,7 +1313,7 @@ bool QAxServerBase::internalCreate() // install an event filter for stock events if (isWidget) { qt.object->installEventFilter(this); - const QList<QWidget*> children = qFindChildren<QWidget*>(qt.object); + const QList<QWidget*> children = qt.object->findChildren<QWidget*>(); QList<QWidget*>::ConstIterator it = children.constBegin(); while (it != children.constEnd()) { (*it)->installEventFilter(this); @@ -2047,10 +2047,10 @@ int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv) if (vt == QVariant::UserType) { if (ptype.endsWith('*')) { variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]); - // qVariantSetValue(variant, *(void**)(argv[p + 1]), ptype); + // variant.setValue(*(void**)(argv[p + 1]), ptype); } else { variant = QVariant(QMetaType::type(ptype), argv[p+1]); - // qVariantSetValue(variant, argv[p + 1], ptype); + // variant.setValue(argv[p + 1], ptype); } } else { variant = QVariant(vt, argv[p + 1]); @@ -2537,7 +2537,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid, if (!type.isEmpty() && pvarResult) { if (!varp[0].isValid() && type != "QVariant") varp[0] = QVariant(QMetaType::type(type), argv_pointer); -// qVariantSetValue(varp[0], argv_pointer[0], type); +// varp[0].setValue(argv_pointer[0], type); ok = QVariantToVARIANT(varp[0], *pvarResult, type); } } @@ -3312,7 +3312,7 @@ HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID) break; { QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font); - QFont qfont = qVariantValue<QFont>(qvar); + QFont qfont = qvariant_cast<QFont>(qvar); qt.widget->setFont(qfont); } break; @@ -3805,7 +3805,7 @@ HRESULT QAxServerBase::internalActivate() // Gone active by now, take care of UIACTIVATE canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode; if (!canTakeFocus && !inDesignMode) { - QList<QWidget*> widgets = qFindChildren<QWidget*>(qt.widget); + QList<QWidget*> widgets = qt.widget->findChildren<QWidget*>(); for (int w = 0; w < widgets.count(); ++w) { QWidget *widget = widgets[w]; canTakeFocus = widget->focusPolicy() != Qt::NoFocus; @@ -3831,13 +3831,13 @@ HRESULT QAxServerBase::internalActivate() if (m_spInPlaceFrame) { hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name)); if (!FAILED(hr)) { - menuBar = (qt.widget && !qax_disable_inplaceframe) ? qFindChild<QMenuBar*>(qt.widget) : 0; + menuBar = (qt.widget && !qax_disable_inplaceframe) ? qt.widget->findChild<QMenuBar*>() : 0; if (menuBar && !menuBar->isVisible()) { createMenu(menuBar); menuBar->hide(); menuBar->installEventFilter(this); } - statusBar = qt.widget ? qFindChild<QStatusBar*>(qt.widget) : 0; + statusBar = qt.widget ? qt.widget->findChild<QStatusBar*>() : 0; if (statusBar && !statusBar->isVisible()) { const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)"); QMetaObject::connect(statusBar, index, this, -1); diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 0cfc7eb..7b2e802 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -954,20 +954,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_I4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.lVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.lVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); #endif else var = (int)arg.lVal; break; case VT_I4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((int)*arg.plVal)); + var = QVariant::fromValue(OLEColorToQColor((int)*arg.plVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); #endif else var = (int)*arg.plVal; @@ -992,20 +992,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_UI4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.ulVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.ulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); #endif else var = (int)arg.ulVal; break; case VT_UI4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((uint)*arg.pulVal)); + var = QVariant::fromValue(OLEColorToQColor((uint)*arg.pulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); #endif else var = (int)*arg.pulVal; @@ -1084,20 +1084,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint if (disp) disp->QueryInterface(IID_IFont, (void**)&ifont); if (ifont) { - var = qVariantFromValue(IFontToQFont(ifont)); + var = QVariant::fromValue(IFontToQFont(ifont)); ifont->Release(); } else { - var = qVariantFromValue(QFont()); + var = QVariant::fromValue(QFont()); } } else if (type == QVariant::Pixmap || (!type && (typeName == "QPixmap" || typeName == "QPixmap*"))) { IPicture *ipic = 0; if (disp) disp->QueryInterface(IID_IPicture, (void**)&ipic); if (ipic) { - var = qVariantFromValue(IPictureToQPixmap(ipic)); + var = QVariant::fromValue(IPictureToQPixmap(ipic)); ipic->Release(); } else { - var = qVariantFromValue(QPixmap()); + var = QVariant::fromValue(QPixmap()); } } else { #ifdef QAX_SERVER @@ -1118,7 +1118,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint #ifndef QAX_SERVER if (typeName == "QVariant") { QAxObject *object = new QAxObject(disp); - var = qVariantFromValue<QAxObject*>(object); + var = QVariant::fromValue<QAxObject*>(object); } else if (typeName != "IDispatch*" && QMetaType::type(typeName)) { QByteArray typeNameStr = QByteArray(typeName); int pIndex = typeName.lastIndexOf('*'); @@ -1145,7 +1145,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint unkn = *arg.ppunkVal; else unkn = arg.punkVal; - qVariantSetValue(var, unkn); + var.setValue(unkn); } break; case VT_ARRAY|VT_VARIANT: diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h index 02ae40a..2856f5e 100644 --- a/src/corelib/concurrent/qfuture.h +++ b/src/corelib/concurrent/qfuture.h @@ -210,7 +210,7 @@ public: bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(Q_CC_XLC) +#if !defined(Q_CC_XLC) template <typename T> QFuture(const QFuture<T> &other) : d(other.d) diff --git a/src/corelib/concurrent/qtconcurrentcompilertest.h b/src/corelib/concurrent/qtconcurrentcompilertest.h index 982a50c..4fbb3d7 100644 --- a/src/corelib/concurrent/qtconcurrentcompilertest.h +++ b/src/corelib/concurrent/qtconcurrentcompilertest.h @@ -51,12 +51,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -#ifdef Q_CC_MSVC -# if _MSC_VER < 1300 -# define QT_CONURRENT_NONSTANDARD_COMPILER -# endif -#endif - #if defined (Q_CC_MSVC) && (_MSC_VER < 1300) # define QT_TYPENAME #else diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.h b/src/corelib/concurrent/qtconcurrentiteratekernel.h index 23aaae8..29d276b 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.h +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h @@ -184,12 +184,9 @@ public: #if defined (QT_NO_STL) : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(false), progressReportingEnabled(true) -#elif !defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) +#else : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true) -#else - : begin(_begin), end(_end), currentIndex(0), - forIteration(selectIteration(std::iterator_category(_begin))), progressReportingEnabled(true) #endif { #if defined (QT_NO_STL) diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp index 9e4189e..f25a494 100644 --- a/src/corelib/concurrent/qthreadpool.cpp +++ b/src/corelib/concurrent/qthreadpool.cpp @@ -41,6 +41,7 @@ #include "qthreadpool.h" #include "qthreadpool_p.h" +#include "qelapsedtimer.h" #ifndef QT_NO_THREAD @@ -288,11 +289,21 @@ void QThreadPoolPrivate::reset() isExiting = false; } -void QThreadPoolPrivate::waitForDone() +bool QThreadPoolPrivate::waitForDone(int msecs) { QMutexLocker locker(&mutex); - while (!(queue.isEmpty() && activeThreads == 0)) - noActiveThreads.wait(locker.mutex()); + if (msecs < 0) { + while (!(queue.isEmpty() && activeThreads == 0)) + noActiveThreads.wait(locker.mutex()); + } else { + QElapsedTimer timer; + timer.start(); + int t; + while (!(queue.isEmpty() && activeThreads == 0) && + ((t = msecs - timer.elapsed()) > 0)) + noActiveThreads.wait(locker.mutex(), t); + } + return queue.isEmpty() && activeThreads == 0; } /*! \internal @@ -617,6 +628,23 @@ void QThreadPool::waitForDone() d->reset(); } +/*! + \overload waitForDone() + \since 4.8 + + Waits up to \a msecs milliseconds for all threads to exit and removes all + threads from the thread pool. Returns true if all threads were removed; + otherwise it returns false. +*/ +bool QThreadPool::waitForDone(int msecs) +{ + Q_D(QThreadPool); + bool rc = d->waitForDone(msecs); + if (rc) + d->reset(); + return rc; +} + QT_END_NAMESPACE #endif diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h index cc1e059..0bd1884 100644 --- a/src/corelib/concurrent/qthreadpool.h +++ b/src/corelib/concurrent/qthreadpool.h @@ -85,6 +85,7 @@ public: void releaseThread(); void waitForDone(); + bool waitForDone(int msecs); }; QT_END_NAMESPACE diff --git a/src/corelib/concurrent/qthreadpool_p.h b/src/corelib/concurrent/qthreadpool_p.h index 8a2cf98..3d2d6be 100644 --- a/src/corelib/concurrent/qthreadpool_p.h +++ b/src/corelib/concurrent/qthreadpool_p.h @@ -82,7 +82,7 @@ public: void startThread(QRunnable *runnable = 0); void reset(); - void waitForDone(); + bool waitForDone(int msecs = -1); bool startFrontRunnable(); void stealRunnable(QRunnable *); diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index d53504a..e0e946b 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -89,7 +89,7 @@ template <typename T> inline void qToUnaligned(const T src, uchar *dest) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest) { return 0 @@ -177,7 +177,7 @@ template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest) { return 0 diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index af35316..a59a74f 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1984,7 +1984,7 @@ QSysInfo::SymbianVersion QSysInfo::symbianVersion() */ void qt_check_pointer(const char *n, int l) { - qWarning("In file %s, line %d: Out of memory", n, l); + qFatal("In file %s, line %d: Out of memory", n, l); } /* \internal @@ -2215,7 +2215,8 @@ void qt_message_output(QtMsgType msgType, const char *buf) _LIT(format, "[Qt Message] %S"); const int maxBlockSize = 256 - ((const TDesC &)format).Length(); const TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf)); - HBufC* hbuffer = q_check_ptr(HBufC::New(qMin(maxBlockSize, ptr.Length()))); + HBufC* hbuffer = HBufC::New(qMin(maxBlockSize, ptr.Length())); + Q_CHECK_PTR(hbuffer); for (int i = 0; i < ptr.Length(); i += hbuffer->Length()) { hbuffer->Des().Copy(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i))); RDebug::Print(format, hbuffer); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 8f27b03..a8758cf 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -44,11 +44,11 @@ #include <stddef.h> -#define QT_VERSION_STR "4.7.0" +#define QT_VERSION_STR "4.8.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x040700 +#define QT_VERSION 0x040800 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -383,31 +383,12 @@ namespace QT_NAMESPACE {} #elif defined(_MSC_VER) # define Q_CC_MSVC -/* proper support of bool for _MSC_VER >= 1100 */ +# define Q_CC_MSVC_NET # define Q_CANNOT_DELETE_CONSTANT # define Q_OUTOFLINE_TEMPLATE inline # define Q_NO_TEMPLATE_FRIENDS -# define QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# define Q_ALIGNOF(type) __alignof(type) -# define Q_DECL_ALIGN(n) __declspec(align(n)) - -/* Visual C++.Net issues for _MSC_VER >= 1300 */ -# if _MSC_VER >= 1300 -# define Q_CC_MSVC_NET -# if _MSC_VER < 1310 || (defined(Q_OS_WIN64) && defined(_M_IA64)) -# define Q_TYPENAME -# else -# undef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# endif -# else -# define Q_NO_USING_KEYWORD -# define QT_NO_MEMBER_TEMPLATES -# endif -# if _MSC_VER < 1310 -# define QT_NO_QOBJECT_CHECK -# define Q_TYPENAME -# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -# endif +# define Q_ALIGNOF(type) __alignof(type) +# define Q_DECL_ALIGN(n) __declspec(align(n)) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_CC_INTEL @@ -924,10 +905,10 @@ redefine to built-in booleans to make autotests work properly */ #endif /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ #ifndef QT_NO_KEYWORDS -# if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) +# if defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) # define for if(0){}else for # endif #endif @@ -951,7 +932,7 @@ redefine to built-in booleans to make autotests work properly */ # define Q_DECL_DEPRECATED Q_DECL_DEPRECATED #elif (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2))) || defined(Q_CC_RVCT) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) -#elif defined(Q_CC_MSVC) && (_MSC_VER >= 1300) +#elif defined(Q_CC_MSVC) # define Q_DECL_DEPRECATED __declspec(deprecated) # if defined (Q_CC_INTEL) # define Q_DECL_VARIABLE_DEPRECATED @@ -1055,7 +1036,7 @@ redefine to built-in booleans to make autotests work properly */ #else # define QT_FASTCALL #endif -# elif defined(Q_CC_MSVC) && (_MSC_VER > 1300 || defined(Q_CC_INTEL)) +# elif defined(Q_CC_MSVC) # define QT_FASTCALL __fastcall # else # define QT_FASTCALL @@ -1362,15 +1343,22 @@ class QDataStream; # else # define Q_GUI_EXPORT_INLINE inline # endif +# if defined(QT_BUILD_COMPAT_LIB) +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline +# else +# define Q_COMPAT_EXPORT_INLINE inline +# endif #elif defined(Q_CC_RVCT) // we force RVCT not to export inlines by passing --visibility_inlines_hidden // so we need to just inline it, rather than exporting and inlining // note: this affects the contents of the DEF files (ie. these functions do not appear) # define Q_CORE_EXPORT_INLINE inline # define Q_GUI_EXPORT_INLINE inline +# define Q_COMPAT_EXPORT_INLINE inline #else # define Q_CORE_EXPORT_INLINE Q_CORE_EXPORT inline # define Q_GUI_EXPORT_INLINE Q_GUI_EXPORT inline +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline #endif /* @@ -1702,7 +1690,7 @@ Q_CORE_EXPORT void qBadAlloc(); #ifdef QT_NO_EXCEPTIONS # if defined(QT_NO_DEBUG) -# define Q_CHECK_PTR(p) qt_noop(); +# define Q_CHECK_PTR(p) qt_noop() # else # define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0) # endif @@ -1716,12 +1704,7 @@ inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } #if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB) # define Q_FUNC_INFO __PRETTY_FUNCTION__ #elif defined(_MSC_VER) - /* MSVC 2002 doesn't have __FUNCSIG__ nor can it handle QT_STRINGIFY. */ -# if _MSC_VER <= 1300 -# define Q_FUNC_INFO __FILE__ "(line number unavailable)" -# else -# define Q_FUNC_INFO __FUNCSIG__ -# endif +# define Q_FUNC_INFO __FUNCSIG__ #else # if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) || defined(Q_OS_SYMBIAN) # define Q_FUNC_INFO __FILE__ "(line number unavailable)" @@ -1971,8 +1954,6 @@ static inline bool qIsNull(float f) qIsDetached - data sharing functionality */ -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - /* The catch-all template. */ @@ -2005,28 +1986,6 @@ public: }; }; -#else - -template <typename T> char QTypeInfoHelper(T*(*)()); -void* QTypeInfoHelper(...); - -template <typename T> inline bool qIsDetached(T &) { return true; } - -template <typename T> -class QTypeInfo -{ -public: - enum { - isPointer = (1 == sizeof(QTypeInfoHelper((T(*)())0))), - isComplex = !isPointer, - isStatic = !isPointer, - isLarge = (sizeof(T)>sizeof(void*)), - isDummy = false - }; -}; - -#endif /* QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION */ - /* Specialize a specific type with: @@ -2043,8 +2002,7 @@ enum { /* TYPEINFO flags */ Q_DUMMY_TYPE = 0x4 }; -#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ -template <> \ +#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \ class QTypeInfo<TYPE > \ { \ public: \ @@ -2058,6 +2016,11 @@ public: \ static inline const char *name() { return #TYPE; } \ } +#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ +template<> \ +Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) + + template <typename T> inline void qSwap(T &value1, T &value2) { @@ -2140,10 +2103,6 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); # pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ # pragma warning(disable: 4710) /* function not inlined */ # pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify -GX */ -# if _MSC_VER < 1300 -# pragma warning(disable: 4284) /* return type for 'type1::operator ->' is 'type2 *' */ - /* (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) */ -# endif # elif defined(Q_CC_BOR) # pragma option -w-inl # pragma option -w-aus @@ -2217,13 +2176,9 @@ public: #define Q_DECLARE_FLAGS(Flags, Enum)\ typedef QFlags<Enum> Flags; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) -#else -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ +#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \ { return QIncompatibleFlag(int(f1) | f2); } -#endif #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \ inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \ @@ -2280,9 +2235,9 @@ template <typename T> inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase *base, const T *) { return static_cast<const QForeachContainer<T> *>(base); } -#if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) +#if defined(Q_CC_MIPS) /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ # define Q_FOREACH(variable,container) \ if(0){}else \ @@ -2639,12 +2594,6 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_QFUTURE #endif -// MSVC 6.0 and MSVC .NET 2002, can`t handle the map(), etc templates, -// but the QFuture class compiles. -#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) -# define QT_NO_CONCURRENT -#endif - // gcc 3 version has problems with some of the // map/filter overloads. #if defined(Q_CC_GNU) && (__GNUC__ < 4) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 68702c4..c66813a 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -533,6 +533,7 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, + AA_X11InitThreads = 9, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 5cd7f0e..137da0e 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,6 +156,11 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication + construction in order to make Xlib calls thread-safe. This + attribute must be set before QApplication is constructed. + + \omitvalue AA_AttributeCount */ diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index d6b6f11..37a093c 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -41,12 +41,16 @@ #include "qabstractfileengine.h" #include "private/qabstractfileengine_p.h" +#ifdef QT_BUILD_CORE_LIB +#include "private/qresource_p.h" +#endif #include "qdatetime.h" #include "qreadwritelock.h" #include "qvariant.h" // built-in handlers #include "qfsfileengine.h" #include "qdiriterator.h" +#include "qstringbuilder.h" QT_BEGIN_NAMESPACE @@ -94,6 +98,8 @@ QT_BEGIN_NAMESPACE \sa QAbstractFileEngine, QAbstractFileEngine::create() */ +static bool qt_file_engine_handlers_in_use = false; + /* All application-wide handlers are stored in this list. The mutex must be acquired to ensure thread safety. @@ -123,6 +129,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers) QAbstractFileEngineHandler::QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); + qt_file_engine_handlers_in_use = true; fileEngineHandlers()->prepend(this); } @@ -134,8 +141,12 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); // Remove this handler from the handler list only if the list is valid. - if (!qt_abstractfileenginehandlerlist_shutDown) - fileEngineHandlers()->removeAll(this); + if (!qt_abstractfileenginehandlerlist_shutDown) { + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + handlers->removeOne(this); + if (handlers->isEmpty()) + qt_file_engine_handlers_in_use = false; + } } /*! @@ -166,33 +177,48 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - { + if (qt_file_engine_handlers_in_use) { QReadLocker locker(fileEngineHandlerMutex()); // check for registered handlers that can load the file - for (int i = 0; i < fileEngineHandlers()->size(); i++) { - if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + for (int i = 0; i < handlers->size(); i++) { + if (QAbstractFileEngine *ret = handlers->at(i)->create(fileName)) return ret; } } #ifdef QT_BUILD_CORE_LIB - if (!fileName.startsWith(QLatin1Char('/'))) { - int prefixSeparator = fileName.indexOf(QLatin1Char(':')); - if (prefixSeparator > 1) { - QString prefix = fileName.left(prefixSeparator); - QString fileNameWithoutPrefix = fileName.mid(prefixSeparator + 1).prepend(QLatin1Char('/')); - const QStringList &paths = QDir::searchPaths(prefix); + for (int prefixSeparator = 0; prefixSeparator < fileName.size(); ++prefixSeparator) { + QChar const ch = fileName[prefixSeparator]; + if (ch == QLatin1Char('/')) + break; + + if (ch == QLatin1Char(':')) { + if (prefixSeparator == 0) + return new QResourceFileEngine(fileName); + + if (prefixSeparator == 1) + break; + + const QStringList &paths = QDir::searchPaths(fileName.left(prefixSeparator)); for (int i = 0; i < paths.count(); i++) { - QString path = paths.at(i); - path.append(fileNameWithoutPrefix); - QAbstractFileEngine *engine = create(path); + QAbstractFileEngine *engine = create(paths.at(i) % QLatin1Char('/') % fileName.mid(prefixSeparator + 1)); if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) { return engine; } delete engine; } + + break; } + + // There's no need to fully validate the prefix here. Consulting the + // unicode tables could be expensive and validation is already + // performed in QDir::setSearchPaths. + // + // if (!ch.isLetterOrNumber()) + // break; } #endif diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 222ba8f..774c4bc 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -85,10 +85,11 @@ public: Qt_4_4 = 10, Qt_4_5 = 11, Qt_4_6 = 12, - Qt_4_7 = Qt_4_6 -#if QT_VERSION >= 0x040800 -#error Add the datastream version for this Qt version + Qt_4_7 = Qt_4_6, Qt_4_8 = Qt_4_7 +#if QT_VERSION >= 0x040900 +#error Add the datastream version for this Qt version + Qt_4_9 = Qt_4_8 #endif }; diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 093312f..a9d5ad4 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -137,10 +137,8 @@ public: inline QNoDebug &nospace() { return *this; } inline QNoDebug &maybeSpace() { return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline QNoDebug &operator<<(const T &) { return *this; } -#endif }; Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); } @@ -285,11 +283,6 @@ Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } inline QNoDebug qDebug() { return QNoDebug(); } #define qDebug QT_NO_QDEBUG_MACRO -#ifdef QT_NO_MEMBER_TEMPLATES -template<typename T> -inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; } -#endif - #endif #if !defined(QT_NO_WARNING_OUTPUT) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index e54d95e..ed51c5d 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1910,7 +1910,8 @@ QString QDir::homePath() /*! Returns the absolute path of the system's temporary directory. - On Unix/Linux systems this is usually \c{/tmp}; on Windows this is + On Unix/Linux systems this is the path in the \c TMPDIR environment + variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is usually the path in the \c TEMP or \c TMP environment variable. Whether a directory separator is added to the end or not, depends on the operating system. diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 249ce0f..71df3c2 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -86,7 +86,8 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, while (it.hasNext()) { QString path = it.next(); QString normalPath = path; - if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) + if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/"))) + || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\"))) #ifdef Q_OS_WINCE && normalPath.size() > 1) #else diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index a1ffb81..511a1a6 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -189,9 +189,15 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) known.insert(path); do { #ifdef Q_OS_WIN - // UNC, skip past the first two elements - if (separatorPos == 0 && tmpPath.startsWith(QLatin1String("//"))) - separatorPos = tmpPath.indexOf(slash, 2); + if (separatorPos == 0) { + if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) { + // UNC, skip past the first two elements + separatorPos = tmpPath.indexOf(slash, 2); + } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) { + // volume root, skip since it can not be a symlink + separatorPos = 2; + } + } if (separatorPos != -1) #endif separatorPos = tmpPath.indexOf(slash, separatorPos + 1); @@ -208,6 +214,8 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); + if(QFileInfo(target).isRelative()) + target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index d83f7ee..774932a 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -880,6 +880,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) # if !defined(QWS) && defined(Q_OS_MAC) || _q_isMacHidden(d->filePath) +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + || d->st.st_flags & UF_HIDDEN +# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # endif ) { ret |= HiddenFlag; @@ -1089,7 +1092,8 @@ QString QFSFileEngine::fileName(FileName file) const int size = PATH_CHUNK_SIZE; while (1) { - s = q_check_ptr((char *) ::realloc(s, size)); + s = (char *) ::realloc(s, size); + Q_CHECK_PTR(s); len = ::readlink(d->nativeFilePath.constData(), s, size); if (len < 0) { ::free(s); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 35fa04b..84120b4 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -154,6 +154,8 @@ static TRUSTEE_W worldTrusteeW; typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; +typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD); +static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0; QT_END_INCLUDE_NAMESPACE @@ -212,6 +214,9 @@ void QFSFileEnginePrivate::resolveLibs() HINSTANCE userenvHnd = LoadLibrary(L"userenv"); if (userenvHnd) ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); + HINSTANCE kernel32 = LoadLibrary(L"kernel32"); + if(kernel32) + ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW"); #endif } } @@ -1285,7 +1290,12 @@ static QString readSymLink(const QString &link) REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); DWORD retsize = 0; if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; @@ -1297,6 +1307,20 @@ static QString readSymLink(const QString &link) } qFree(rdb); CloseHandle(handle); + +#if !defined(QT_NO_LIBRARY) + QFSFileEnginePrivate::resolveLibs(); + if (ptrGetVolumePathNamesForVolumeNameW) { + QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); + if(matchVolName.indexIn(result) == 0) { + DWORD len; + wchar_t buffer[MAX_PATH]; + QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); + if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0) + result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); + } + } +#endif } #else Q_UNUSED(link); @@ -1548,7 +1572,7 @@ bool QFSFileEnginePrivate::isSymlink() const if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { is_link = true; } } @@ -1648,10 +1672,12 @@ QString QFSFileEngine::fileName(FileName file) const if (!isRelativePath()) { #if !defined(Q_OS_WINCE) - if ((d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') - && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt - d->filePath.startsWith(QLatin1Char('/')) // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt - ) { + if (d->filePath.startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt + d->filePath.size() == 2 || // It's a drive letter that needs to get a working dir appended + (d->filePath.size() > 2 && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt + d->filePath.contains(QLatin1String("/../")) || d->filePath.contains(QLatin1String("/./")) || + d->filePath.endsWith(QLatin1String("/..")) || d->filePath.endsWith(QLatin1String("/."))) + { ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath)); } else { ret = d->filePath; diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index ce9c57e..929885c 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1185,21 +1185,6 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) return false; } -//file type handler -class QResourceFileEngineHandler : public QAbstractFileEngineHandler -{ -public: - QResourceFileEngineHandler() { } - ~QResourceFileEngineHandler() { } - QAbstractFileEngine *create(const QString &path) const; -}; -QAbstractFileEngine *QResourceFileEngineHandler::create(const QString &path) const -{ - if (path.size() > 0 && path.startsWith(QLatin1Char(':'))) - return new QResourceFileEngine(path); - return 0; -} - //resource engine class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate { @@ -1506,12 +1491,6 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr) return true; } -//Initialization and cleanup -Q_GLOBAL_STATIC(QResourceFileEngineHandler, resource_file_handler) - -static int qt_force_resource_init() { resource_file_handler(); return 1; } -Q_CORE_EXPORT void qInitResourceIO() { resource_file_handler(); } -static int qt_forced_resource_init = qt_force_resource_init(); -Q_CONSTRUCTOR_FUNCTION(qt_force_resource_init) +Q_CORE_EXPORT void qInitResourceIO() { } // ### Qt 5: remove QT_END_NAMESPACE diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index f802412..384804a 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -252,9 +252,7 @@ bool QConfFile::isWritable() const } else { // Create the directories to the file. QDir dir(fileInfo.absolutePath()); - if (dir.exists() && dir.isReadable()) { - return true; - } else { + if (!dir.exists()) { if (!dir.mkpath(dir.absolutePath())) return false; } diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 79a8ce4..20ec995 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -966,14 +966,14 @@ static void QT_FASTCALL _fragment(const char **ptr, QUrlParseData *parseData) } struct NameprepCaseFoldingEntry { - int uc; + uint uc; ushort mapping[4]; }; -inline bool operator<(int one, const NameprepCaseFoldingEntry &other) +inline bool operator<(uint one, const NameprepCaseFoldingEntry &other) { return one < other.uc; } -inline bool operator<(const NameprepCaseFoldingEntry &one, int other) +inline bool operator<(const NameprepCaseFoldingEntry &one, uint other) { return one.uc < other; } static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { @@ -1862,45 +1862,44 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { { 0xFF38, { 0xFF58, 0x0000, 0x0000, 0x0000 } }, { 0xFF39, { 0xFF59, 0x0000, 0x0000, 0x0000 } }, { 0xFF3A, { 0xFF5A, 0x0000, 0x0000, 0x0000 } }, - // ##### -/* { 0x10400, { 0x10428, 0x0000, 0x0000, 0x0000 } }, - { 0x10401, { 0x10429, 0x0000, 0x0000, 0x0000 } }, - { 0x10402, { 0x1042A, 0x0000, 0x0000, 0x0000 } }, - { 0x10403, { 0x1042B, 0x0000, 0x0000, 0x0000 } }, - { 0x10404, { 0x1042C, 0x0000, 0x0000, 0x0000 } }, - { 0x10405, { 0x1042D, 0x0000, 0x0000, 0x0000 } }, - { 0x10406, { 0x1042E, 0x0000, 0x0000, 0x0000 } }, - { 0x10407, { 0x1042F, 0x0000, 0x0000, 0x0000 } }, - { 0x10408, { 0x10430, 0x0000, 0x0000, 0x0000 } }, - { 0x10409, { 0x10431, 0x0000, 0x0000, 0x0000 } }, - { 0x1040A, { 0x10432, 0x0000, 0x0000, 0x0000 } }, - { 0x1040B, { 0x10433, 0x0000, 0x0000, 0x0000 } }, - { 0x1040C, { 0x10434, 0x0000, 0x0000, 0x0000 } }, - { 0x1040D, { 0x10435, 0x0000, 0x0000, 0x0000 } }, - { 0x1040E, { 0x10436, 0x0000, 0x0000, 0x0000 } }, - { 0x1040F, { 0x10437, 0x0000, 0x0000, 0x0000 } }, - { 0x10410, { 0x10438, 0x0000, 0x0000, 0x0000 } }, - { 0x10411, { 0x10439, 0x0000, 0x0000, 0x0000 } }, - { 0x10412, { 0x1043A, 0x0000, 0x0000, 0x0000 } }, - { 0x10413, { 0x1043B, 0x0000, 0x0000, 0x0000 } }, - { 0x10414, { 0x1043C, 0x0000, 0x0000, 0x0000 } }, - { 0x10415, { 0x1043D, 0x0000, 0x0000, 0x0000 } }, - { 0x10416, { 0x1043E, 0x0000, 0x0000, 0x0000 } }, - { 0x10417, { 0x1043F, 0x0000, 0x0000, 0x0000 } }, - { 0x10418, { 0x10440, 0x0000, 0x0000, 0x0000 } }, - { 0x10419, { 0x10441, 0x0000, 0x0000, 0x0000 } }, - { 0x1041A, { 0x10442, 0x0000, 0x0000, 0x0000 } }, - { 0x1041B, { 0x10443, 0x0000, 0x0000, 0x0000 } }, - { 0x1041C, { 0x10444, 0x0000, 0x0000, 0x0000 } }, - { 0x1041D, { 0x10445, 0x0000, 0x0000, 0x0000 } }, - { 0x1041E, { 0x10446, 0x0000, 0x0000, 0x0000 } }, - { 0x1041F, { 0x10447, 0x0000, 0x0000, 0x0000 } }, - { 0x10420, { 0x10448, 0x0000, 0x0000, 0x0000 } }, - { 0x10421, { 0x10449, 0x0000, 0x0000, 0x0000 } }, - { 0x10422, { 0x1044A, 0x0000, 0x0000, 0x0000 } }, - { 0x10423, { 0x1044B, 0x0000, 0x0000, 0x0000 } }, - { 0x10424, { 0x1044C, 0x0000, 0x0000, 0x0000 } }, - { 0x10425, { 0x1044D, 0x0000, 0x0000, 0x0000 } },*/ + { 0x10400, { 0xd801, 0xdc28, 0x0000, 0x0000 } }, + { 0x10401, { 0xd801, 0xdc29, 0x0000, 0x0000 } }, + { 0x10402, { 0xd801, 0xdc2A, 0x0000, 0x0000 } }, + { 0x10403, { 0xd801, 0xdc2B, 0x0000, 0x0000 } }, + { 0x10404, { 0xd801, 0xdc2C, 0x0000, 0x0000 } }, + { 0x10405, { 0xd801, 0xdc2D, 0x0000, 0x0000 } }, + { 0x10406, { 0xd801, 0xdc2E, 0x0000, 0x0000 } }, + { 0x10407, { 0xd801, 0xdc2F, 0x0000, 0x0000 } }, + { 0x10408, { 0xd801, 0xdc30, 0x0000, 0x0000 } }, + { 0x10409, { 0xd801, 0xdc31, 0x0000, 0x0000 } }, + { 0x1040A, { 0xd801, 0xdc32, 0x0000, 0x0000 } }, + { 0x1040B, { 0xd801, 0xdc33, 0x0000, 0x0000 } }, + { 0x1040C, { 0xd801, 0xdc34, 0x0000, 0x0000 } }, + { 0x1040D, { 0xd801, 0xdc35, 0x0000, 0x0000 } }, + { 0x1040E, { 0xd801, 0xdc36, 0x0000, 0x0000 } }, + { 0x1040F, { 0xd801, 0xdc37, 0x0000, 0x0000 } }, + { 0x10410, { 0xd801, 0xdc38, 0x0000, 0x0000 } }, + { 0x10411, { 0xd801, 0xdc39, 0x0000, 0x0000 } }, + { 0x10412, { 0xd801, 0xdc3A, 0x0000, 0x0000 } }, + { 0x10413, { 0xd801, 0xdc3B, 0x0000, 0x0000 } }, + { 0x10414, { 0xd801, 0xdc3C, 0x0000, 0x0000 } }, + { 0x10415, { 0xd801, 0xdc3D, 0x0000, 0x0000 } }, + { 0x10416, { 0xd801, 0xdc3E, 0x0000, 0x0000 } }, + { 0x10417, { 0xd801, 0xdc3F, 0x0000, 0x0000 } }, + { 0x10418, { 0xd801, 0xdc40, 0x0000, 0x0000 } }, + { 0x10419, { 0xd801, 0xdc41, 0x0000, 0x0000 } }, + { 0x1041A, { 0xd801, 0xdc42, 0x0000, 0x0000 } }, + { 0x1041B, { 0xd801, 0xdc43, 0x0000, 0x0000 } }, + { 0x1041C, { 0xd801, 0xdc44, 0x0000, 0x0000 } }, + { 0x1041D, { 0xd801, 0xdc45, 0x0000, 0x0000 } }, + { 0x1041E, { 0xd801, 0xdc46, 0x0000, 0x0000 } }, + { 0x1041F, { 0xd801, 0xdc47, 0x0000, 0x0000 } }, + { 0x10420, { 0xd801, 0xdc48, 0x0000, 0x0000 } }, + { 0x10421, { 0xd801, 0xdc49, 0x0000, 0x0000 } }, + { 0x10422, { 0xd801, 0xdc4A, 0x0000, 0x0000 } }, + { 0x10423, { 0xd801, 0xdc4B, 0x0000, 0x0000 } }, + { 0x10424, { 0xd801, 0xdc4C, 0x0000, 0x0000 } }, + { 0x10425, { 0xd801, 0xdc4D, 0x0000, 0x0000 } }, { 0x1D400, { 0x0061, 0x0000, 0x0000, 0x0000 } }, { 0x1D401, { 0x0062, 0x0000, 0x0000, 0x0000 } }, { 0x1D402, { 0x0063, 0x0000, 0x0000, 0x0000 } }, @@ -2355,17 +2354,23 @@ static void mapToLowerCase(QString *str, int from) { int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); - QChar *d = 0; + ushort *d = 0; for (int i = from; i < str->size(); ++i) { - int uc = str->at(i).unicode(); + uint uc = str->at(i).unicode(); if (uc < 0x80) { if (uc <= 'Z' && uc >= 'A') { - uc |= 0x20; if (!d) - d = str->data(); - d[i] = QChar(uc); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = (uc | 0x20); } } else { + if (QChar(uc).isHighSurrogate() && i < str->size() - 1) { + ushort low = str->at(i + 1).unicode(); + if (QChar(low).isLowSurrogate()) { + uc = QChar::surrogateToUcs4(uc, low); + ++i; + } + } const NameprepCaseFoldingEntry *entry = qBinaryFind(NameprepCaseFolding, NameprepCaseFolding + N, uc); @@ -2374,23 +2379,26 @@ static void mapToLowerCase(QString *str, int from) while (l < 4 && entry->mapping[l]) ++l; if (l > 1) { - str->replace(i, 1, (const QChar *)&entry->mapping[0], l); + if (uc <= 0xffff) + str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); + else + str->replace(i-1, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); d = 0; } else { if (!d) - d = str->data(); - d[i] = QChar(entry->mapping[0]); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = entry->mapping[0]; } } } } } -static bool isMappedToNothing(const QChar &ch) +static bool isMappedToNothing(uint uc) { - if (ch.unicode() < 0xad) + if (uc < 0xad) return false; - switch (ch.unicode()) { + switch (uc) { case 0x00AD: case 0x034F: case 0x1806: case 0x180B: case 0x180C: case 0x180D: case 0x200B: case 0x200C: case 0x200D: case 0x2060: case 0xFE00: case 0xFE01: case 0xFE02: case 0xFE03: case 0xFE04: case 0xFE05: case 0xFE06: case 0xFE07: @@ -2409,66 +2417,72 @@ static void stripProhibitedOutput(QString *str, int from) const ushort *in = out; const ushort *end = (ushort *)str->data() + str->size(); while (in < end) { - ushort uc = *in; - if (uc < 0x80 || - !(uc <= 0x009F - || uc == 0x00A0 - || uc == 0x0340 - || uc == 0x0341 - || uc == 0x06DD - || uc == 0x070F - || uc == 0x1680 - || uc == 0x180E - || (uc >= 0x2000 && uc <= 0x200B) - || uc == 0x200C - || uc == 0x200D - || uc == 0x200E - || uc == 0x200F - || (uc >= 0x2028 && uc <= 0x202F) - || uc == 0x205F - || (uc >= 0x2060 && uc <= 0x2063) - || uc == 0x206A - || (uc >= 0x206A && uc <= 0x206F) - || (uc >= 0x2FF0 && uc <= 0x2FFB) - || uc == 0x3000 - || (uc >= 0xD800 && uc <= 0xDFFF) - || (uc >= 0xE000 && uc <= 0xF8FF) - || (uc >= 0xFDD0 && uc <= 0xFDEF) - || uc == 0xFEFF - || (uc >= 0xFFF9 && uc <= 0xFFFC) - || (uc >= 0xFFFA && (uc <= 0xFFFE || uc == 0xFFFF)) - /* ### Add NAMEPREP support for surrogates - || uc == 0xE0001 - || (uc >= 0x2FFFE && uc <= 0x2FFFF) - || (uc >= 0x1D173 && uc <= 0x1D17A) - || (uc >= 0x1FFFE && uc <= 0x1FFFF) - || (uc >= 0x3FFFE && uc <= 0x3FFFF) - || (uc >= 0x4FFFE && uc <= 0x4FFFF) - || (uc >= 0x5FFFE && uc <= 0x5FFFF) - || (uc >= 0x6FFFE && uc <= 0x6FFFF) - || (uc >= 0x7FFFE && uc <= 0x7FFFF) - || (uc >= 0x8FFFE && uc <= 0x8FFFF) - || (uc >= 0x9FFFE && uc <= 0x9FFFF) - || (uc >= 0xAFFFE && uc <= 0xAFFFF) - || (uc >= 0xBFFFE && uc <= 0xBFFFF) - || (uc >= 0xCFFFE && uc <= 0xCFFFF) - || (uc >= 0xDFFFE && uc <= 0xDFFFF) - || (uc >= 0xE0020 && uc <= 0xE007F) - || (uc >= 0xEFFFE && uc <= 0xEFFFF) - || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0xFFFFE && uc <= 0xFFFFF) - || (uc >= 0x100000 && uc <= 0x10FFFD) - || (uc >= 0x10FFFE && uc <= 0x10FFFF)*/)) - *out++ = *in; + uint uc = *in; + if (QChar(uc).isHighSurrogate() && in < end - 1) { + ushort low = *(in + 1); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (uc <= 0xFFFF) { + if (uc < 0x80 || + !(uc <= 0x009F + || uc == 0x00A0 + || uc == 0x0340 + || uc == 0x0341 + || uc == 0x06DD + || uc == 0x070F + || uc == 0x1680 + || uc == 0x180E + || (uc >= 0x2000 && uc <= 0x200F) + || (uc >= 0x2028 && uc <= 0x202F) + || uc == 0x205F + || (uc >= 0x2060 && uc <= 0x2063) + || (uc >= 0x206A && uc <= 0x206F) + || (uc >= 0x2FF0 && uc <= 0x2FFB) + || uc == 0x3000 + || (uc >= 0xD800 && uc <= 0xDFFF) + || (uc >= 0xE000 && uc <= 0xF8FF) + || (uc >= 0xFDD0 && uc <= 0xFDEF) + || uc == 0xFEFF + || (uc >= 0xFFF9 && uc <= 0xFFFF))) { + *out++ = *in; + } + } else { + if (!((uc >= 0x1D173 && uc <= 0x1D17A) + || (uc >= 0x1FFFE && uc <= 0x1FFFF) + || (uc >= 0x2FFFE && uc <= 0x2FFFF) + || (uc >= 0x3FFFE && uc <= 0x3FFFF) + || (uc >= 0x4FFFE && uc <= 0x4FFFF) + || (uc >= 0x5FFFE && uc <= 0x5FFFF) + || (uc >= 0x6FFFE && uc <= 0x6FFFF) + || (uc >= 0x7FFFE && uc <= 0x7FFFF) + || (uc >= 0x8FFFE && uc <= 0x8FFFF) + || (uc >= 0x9FFFE && uc <= 0x9FFFF) + || (uc >= 0xAFFFE && uc <= 0xAFFFF) + || (uc >= 0xBFFFE && uc <= 0xBFFFF) + || (uc >= 0xCFFFE && uc <= 0xCFFFF) + || (uc >= 0xDFFFE && uc <= 0xDFFFF) + || uc == 0xE0001 + || (uc >= 0xE0020 && uc <= 0xE007F) + || (uc >= 0xEFFFE && uc <= 0xEFFFF) + || (uc >= 0xF0000 && uc <= 0xFFFFD) + || (uc >= 0xFFFFE && uc <= 0xFFFFF) + || (uc >= 0x100000 && uc <= 0x10FFFD) + || (uc >= 0x10FFFE && uc <= 0x10FFFF))) { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } ++in; } if (in != out) str->truncate(out - str->utf16()); } -static bool isBidirectionalRorAL(const QChar &c) +static bool isBidirectionalRorAL(uint uc) { - ushort uc = c.unicode(); if (uc < 0x5b0) return false; return uc == 0x05BE @@ -2507,9 +2521,8 @@ static bool isBidirectionalRorAL(const QChar &c) || (uc >= 0xFE76 && uc <= 0xFEFC); } -static bool isBidirectionalL(const QChar &ch) +static bool isBidirectionalL(uint uc) { - ushort uc = ch.unicode(); if (uc < 0xaa) return (uc >= 0x0041 && uc <= 0x005A) || (uc >= 0x0061 && uc <= 0x007A); @@ -2874,8 +2887,7 @@ static bool isBidirectionalL(const QChar &ch) return true; } - /* ### Add NAMEPREP support for surrogates - || (uc >= 0x10300 && uc <= 0x1031E) + if ((uc >= 0x10300 && uc <= 0x1031E) || (uc >= 0x10320 && uc <= 0x10323) || (uc >= 0x10330 && uc <= 0x1034A) || (uc >= 0x10400 && uc <= 0x10425) @@ -2911,7 +2923,9 @@ static bool isBidirectionalL(const QChar &ch) || (uc >= 0x20000 && uc <= 0x2A6D6) || (uc >= 0x2F800 && uc <= 0x2FA1D) || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0x100000 && uc <= 0x10FFFD)*/ + || (uc >= 0x100000 && uc <= 0x10FFFD)) { + return true; + } return false; } @@ -2944,13 +2958,37 @@ void qt_nameprep(QString *source, int from) return; // everything was mapped easily (lowercased, actually) int firstNonAscii = out - src; + // Characters unassigned in Unicode 3.2 are not allowed in "stored string" scheme + // but allowed in "query" scheme + // (Table A.1) + const bool isUnassignedAllowed = false; // ### // Characters commonly mapped to nothing are simply removed // (Table B.1) const QChar *in = out; - while (in < e) { - if (!isMappedToNothing(*in)) - *out++ = *in; - ++in; + for ( ; in < e; ++in) { + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (!isUnassignedAllowed) { + QChar::UnicodeVersion version = QChar::unicodeVersion(uc); + if (version == QChar::Unicode_Unassigned || version > QChar::Unicode_3_2) { + source->resize(from); // not allowed, clear the label + return; + } + } + if (!isMappedToNothing(uc)) { + if (uc <= 0xFFFF) { + *out++ = *in; + } else { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } } if (out != in) source->truncate(out - src); @@ -2961,7 +2999,8 @@ void qt_nameprep(QString *source, int from) // Normalize to Unicode 3.2 form KC extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from); - qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); + qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, + firstNonAscii > from ? firstNonAscii - 1 : from); // Strip prohibited output stripProhibitedOutput(source, firstNonAscii); @@ -2972,14 +3011,22 @@ void qt_nameprep(QString *source, int from) src = source->data(); e = src + source->size(); for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { - if (isBidirectionalL(*in)) + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (isBidirectionalL(uc)) containsLCat = true; - else if (isBidirectionalRorAL(*in)) + else if (isBidirectionalRorAL(uc)) containsRandALCat = true; } if (containsRandALCat) { - if (containsLCat || (!isBidirectionalRorAL(src[from]) - || !isBidirectionalRorAL(e[-1]))) + if (containsLCat || (!isBidirectionalRorAL(src[from].unicode()) + || !isBidirectionalRorAL(e[-1].unicode()))) source->resize(from); // not allowed, clear the label } } @@ -5987,19 +6034,22 @@ bool QUrl::isDetached() const /*! - Returns a QUrl representation of \a localFile, interpreted as a - local file. + Returns a QUrl representation of \a localFile, interpreted as a local + file. This function accepts paths separated by slashes as well as the + native separator for this platform. - \sa toLocalFile() + This function also accepts paths with a doubled leading slash (or + backslash) to indicate a remote file, as in + "//servername/path/to/file.txt". Note that only certain platforms can + actually open this file using QFile::open(). + + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators */ QUrl QUrl::fromLocalFile(const QString &localFile) { QUrl url; url.setScheme(QLatin1String("file")); - QString deslashified = localFile; - deslashified.replace(QLatin1Char('\\'), QLatin1Char('/')); - - + QString deslashified = QDir::fromNativeSeparators(localFile); // magic for drives on windows if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) { @@ -6018,35 +6068,61 @@ QUrl QUrl::fromLocalFile(const QString &localFile) } /*! - Returns the path of this URL formatted as a local file path. + Returns the path of this URL formatted as a local file path. The path + returned will use forward slashes, even if it was originally created + from one with backslashes. - \sa fromLocalFile() + If this URL contains a non-empty hostname, it will be encoded in the + returned value in the form found on SMB networks (for example, + "//servername/path/to/file.txt"). + + \sa fromLocalFile(), isLocalFile() */ QString QUrl::toLocalFile() const { - if (!d) return QString(); - if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + // the call to isLocalFile() also ensures that we're parsed + if (!isLocalFile()) + return QString(); QString tmp; QString ourPath = path(); - if (d->scheme.isEmpty() || QString::compare(d->scheme, QLatin1String("file"), Qt::CaseInsensitive) == 0) { - // magic for shared drive on windows - if (!d->host.isEmpty()) { - tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') - ? QLatin1Char('/') + ourPath : ourPath); - } else { - tmp = ourPath; - // magic for drives on windows - if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) - tmp.remove(0, 1); - } + // magic for shared drive on windows + if (!d->host.isEmpty()) { + tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') + ? QLatin1Char('/') + ourPath : ourPath); + } else { + tmp = ourPath; + // magic for drives on windows + if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) + tmp.remove(0, 1); } return tmp; } /*! + \since 4.7 + Returns true if this URL is pointing to a local file path. A URL is a + local file path if the scheme is "file". + + Note that this function considers URLs with hostnames to be local file + paths, even if the eventual file path cannot be opened with + QFile::open(). + + \sa fromLocalFile(), toLocalFile() +*/ +bool QUrl::isLocalFile() const +{ + if (!d) return false; + if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + + if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0) + return false; // not file + return true; +} + +/*! Returns true if this URL is a parent of \a childUrl. \a childUrl is a child of this URL if the two URLs share the same scheme and authority, and this URL's path is a parent of the path of \a childUrl. diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 6f8331a..162aa7c 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -183,6 +183,7 @@ public: static QUrl fromLocalFile(const QString &localfile); QString toLocalFile() const; + bool isLocalFile() const; QString toString(FormattingOptions options = None) const; diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index e3fce18..3a6395b 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -532,7 +532,7 @@ bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVaria case 1: //floating point return v1.toReal() < v2.toReal(); default: - return v1.toString() < v2.toString(); + return v1.toString().localeAwareCompare(v2.toString()) < 0; } } diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 5afde9a..073ed6b 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -61,7 +61,8 @@ Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString) #else TPtrC16 ptr(qt_QString2TPtrC(aString)); #endif - buffer = q_check_ptr(HBufC::New(ptr.Length())); + buffer = HBufC::New(ptr.Length()); + Q_CHECK_PTR(buffer); buffer->Des().Copy(ptr); return buffer; } @@ -81,8 +82,9 @@ QHBufC::QHBufC() } QHBufC::QHBufC(const QHBufC &src) - : m_hBufC(q_check_ptr(src.m_hBufC->Alloc())) + : m_hBufC(src.m_hBufC->Alloc()) { + Q_CHECK_PTR(m_hBufC); } /*! diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 512e193..ad645e3 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -122,6 +122,11 @@ static SystemDriveFunc PtrGetSystemDrive=0; extern QString qAppFileName(); #endif +int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 +#if defined(QT3_SUPPORT) +bool QCoreApplicationPrivate::useQt3Support = true; +#endif + #if !defined(Q_OS_WIN) #ifdef Q_OS_MAC QString QCoreApplicationPrivate::macMenuBarName() @@ -263,10 +268,14 @@ struct QCoreApplicationData { Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata) -QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv) +QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags) : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0), in_exec(false), aboutToQuitEmitted(false) { + app_compile_version = flags & 0xffffff; +#if defined(QT3_SUPPORT) + useQt3Support = !(flags & 0x01000000); +#endif static const char *const empty = ""; if (argc == 0 || argv == 0) { argc = 0; @@ -511,7 +520,7 @@ void QCoreApplication::flush() one valid character string. */ QCoreApplication::QCoreApplication(int &argc, char **argv) - : QObject(*new QCoreApplicationPrivate(argc, argv)) + : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000)) { init(); QCoreApplicationPrivate::eventDispatcher->startingUp(); @@ -527,6 +536,25 @@ QCoreApplication::QCoreApplication(int &argc, char **argv) #endif } +QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal) +: QObject(*new QCoreApplicationPrivate(argc, argv, _internal)) +{ + init(); + QCoreApplicationPrivate::eventDispatcher->startingUp(); +#if defined(Q_OS_SYMBIAN) +#ifndef QT_NO_LIBRARY + // Refresh factoryloader, as text codecs are requested during lib path + // resolving process and won't be therefore properly loaded. + // Unknown if this is symbian specific issue. + QFactoryLoader::refreshAll(); +#endif +#ifndef QT_NO_SYSTEMLOCALE + d_func()->symbianInit(); +#endif +#endif //Q_OS_SYMBIAN +} + + // ### move to QCoreApplicationPrivate constructor? void QCoreApplication::init() { @@ -805,11 +833,6 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (event->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(event)->child()); -#endif // QT3_SUPPORT - return receiver->isWidgetType() ? false : d->notify_helper(receiver, event); } @@ -1019,6 +1042,7 @@ int QCoreApplication::exec() return returnCode; } + /*! Tells the application to exit with a return code. @@ -1475,7 +1499,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) --pe.receiver->d_func()->postedEvents; #ifdef QT3_SUPPORT if (pe.event->type() == QEvent::ChildInsertedRequest) - pe.receiver->d_func()->removePendingChildInsertedEvents(0); + pe.receiver->d_func()->pendingChildInsertedEvents.clear(); #endif pe.event->posted = false; events.append(pe.event); diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index d87103e..f1c7c26 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -78,7 +78,23 @@ class Q_CORE_EXPORT QCoreApplication : public QObject Q_DECLARE_PRIVATE(QCoreApplication) public: - QCoreApplication(int &argc, char **argv); + enum { ApplicationFlags = QT_VERSION +#if !defined(QT3_SUPPORT) + | 0x01000000 +#endif + }; + +#if defined(QT_BUILD_CORE_LIB) || defined(qdoc) + QCoreApplication(int &argc, char **argv); // ### Qt5 remove +#endif +#if !defined(qdoc) + QCoreApplication(int &argc, char **argv, int +#if !defined(QT_BUILD_CORE_LIB) + = ApplicationFlags +#endif + ); +#endif + ~QCoreApplication(); #ifdef QT_DEPRECATED diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index e066137..2355c37 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -75,7 +75,7 @@ class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QCoreApplication) public: - QCoreApplicationPrivate(int &aargc, char **aargv); + QCoreApplicationPrivate(int &aargc, char **aargv, uint flags); ~QCoreApplicationPrivate(); bool sendThroughApplicationEventFilters(QObject *, QEvent *); @@ -129,6 +129,10 @@ public: static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } + static int app_compile_version; +#if defined(QT3_SUPPORT) + static bool useQt3Support; +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 1bad8ed..5ab867f 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1009,7 +1009,8 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - QSocketActiveObject *socketAO = q_check_ptr(new QSocketActiveObject(this, notifier)); + QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + Q_CHECK_PTR(socketAO); m_notifiers.insert(notifier, socketAO); selectThread().requestSocketEvents(notifier, &socketAO->iStatus); } diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9854e68..a70772f 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1558,6 +1558,12 @@ bool QMetaMethod::invoke(QObject *object, : Qt::QueuedConnection; } +#ifdef QT_NO_THREAD + if (connectionType == Qt::BlockingQueuedConnection) { + connectionType = Qt::DirectConnection; + } +#endif + // invoke! void *param[] = { returnValue.data(), @@ -1576,7 +1582,7 @@ bool QMetaMethod::invoke(QObject *object, int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; - } else { + } else if (connectionType == Qt::QueuedConnection) { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " "queued connections"); @@ -1609,40 +1615,21 @@ bool QMetaMethod::invoke(QObject *object, } } - if (connectionType == Qt::QueuedConnection) { - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); - } else { - if (currentThread == objectThread) { - qWarning("QMetaMethod::invoke: Dead lock detected in " - "BlockingQueuedConnection: Receiver is %s(%p)", - mobj->className(), object); - } + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, nargs, types, args)); + } else { // blocking queued connection +#ifndef QT_NO_THREAD + if (currentThread == objectThread) { + qWarning("QMetaMethod::invoke: Dead lock detected in " + "BlockingQueuedConnection: Receiver is %s(%p)", + mobj->className(), object); + } - // blocking queued connection -#ifdef QT_NO_THREAD - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); -#else - QSemaphore semaphore; - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args, - &semaphore)); - semaphore.acquire(); + QSemaphore semaphore; + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, 0, 0, param, &semaphore)); + semaphore.acquire(); #endif // QT_NO_THREAD - } } return true; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index b700351..8124487 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -138,6 +138,8 @@ private: const QMetaObject *mobj; uint handle; friend struct QMetaObject; + friend struct QMetaObjectPrivate; + friend class QObject; }; Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE); diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 4a03874..40b8715 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -131,6 +131,8 @@ struct QMetaObjectPrivate #ifndef QT_NO_QOBJECT //defined in qobject.cpp enum DisconnectType { DisconnectAll, DisconnectOne }; + static void memberIndexes(const QObject *obj, const QMetaMethod &member, + int *signalIndex, int *methodIndex); static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index fef02cf..bb77d2c 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -311,6 +311,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong), QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong), QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char), + QT_ADD_STATIC_METATYPE("signed char", QMetaType::Char), QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar), QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short), QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort), diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 2108b92..52efcd0 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -355,6 +355,7 @@ Q_DECLARE_BUILTIN_METATYPE(QChar, QChar) Q_DECLARE_BUILTIN_METATYPE(long, Long) Q_DECLARE_BUILTIN_METATYPE(short, Short) Q_DECLARE_BUILTIN_METATYPE(char, Char) +Q_DECLARE_BUILTIN_METATYPE(signed char, Char) Q_DECLARE_BUILTIN_METATYPE(ulong, ULong) Q_DECLARE_BUILTIN_METATYPE(ushort, UShort) Q_DECLARE_BUILTIN_METATYPE(uchar, UChar) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8330e47..ceffa66 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -149,9 +149,11 @@ QObjectPrivate::QObjectPrivate(int version) postedEvents = 0; extraData = 0; connectedSignals[0] = connectedSignals[1] = 0; - inEventHandler = false; inThreadChangeEvent = false; +#ifdef QT_JAMBI_BUILD + inEventHandler = false; deleteWatch = 0; +#endif metaObject = 0; hasGuards = false; } @@ -159,8 +161,10 @@ QObjectPrivate::QObjectPrivate(int version) QObjectPrivate::~QObjectPrivate() { delete static_cast<QAbstractDynamicMetaObject*>(metaObject); +#ifdef QT_JAMBI_BUILD if (deleteWatch) *deleteWatch = 1; +#endif #ifndef QT_NO_USERDATA if (extraData) qDeleteAll(extraData->userData); @@ -169,6 +173,7 @@ QObjectPrivate::~QObjectPrivate() } +#ifdef QT_JAMBI_BUILD int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) { int *old = d->deleteWatch; d->deleteWatch = w; @@ -183,18 +188,15 @@ void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int dele if (oldWatch) *oldWatch = deleteWatch; } - - - - +#endif #ifdef QT3_SUPPORT void QObjectPrivate::sendPendingChildInsertedEvents() { Q_Q(QObject); for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *c = pendingChildInsertedEvents.at(i); - if (!c) + QObject *c = pendingChildInsertedEvents.at(i).data(); + if (!c || c->parent() != q) continue; QChildEvent childEvent(QEvent::ChildInserted, c); QCoreApplication::sendEvent(q, &childEvent); @@ -202,26 +204,6 @@ void QObjectPrivate::sendPendingChildInsertedEvents() pendingChildInsertedEvents.clear(); } -void QObjectPrivate::removePendingChildInsertedEvents(QObject *child) -{ - if (!child) { - pendingChildInsertedEvents.clear(); - return; - } - - // the QObject destructor calls QObject::removeChild, which calls - // QCoreApplication::sendEvent() directly. this can happen while the event - // loop is in the middle of posting events, and when we get here, we may - // not have any more posted events for this object. - - // if this is a child remove event and the child insert hasn't - // been dispatched yet, kill that insert - for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *&c = pendingChildInsertedEvents[i]; - if (c == child) - c = 0; - } -} #endif @@ -476,11 +458,6 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (!priv->hasGuards) - return; - GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -515,12 +492,14 @@ QMetaCallEvent::QMetaCallEvent(int id, const QObject *sender, int signalId, */ QMetaCallEvent::~QMetaCallEvent() { - for (int i = 0; i < nargs_; ++i) { - if (types_[i] && args_[i]) - QMetaType::destroy(types_[i], args_[i]); + if (types_) { + for (int i = 0; i < nargs_; ++i) { + if (types_[i] && args_[i]) + QMetaType::destroy(types_[i], args_[i]); + } + qFree(types_); + qFree(args_); } - if (types_) qFree(types_); - if (args_) qFree(args_); #ifndef QT_NO_THREAD if (semaphore_) semaphore_->release(); @@ -730,13 +709,15 @@ QObject::QObject(QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; + } } qt_addObject(this); } @@ -755,9 +736,11 @@ QObject::QObject(QObject *parent, const char *name) qt_addObject(d_ptr->q_ptr = this); d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); + if (parent) { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } setObjectName(QString::fromAscii(name)); } #endif @@ -771,21 +754,23 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - if (d->isWidget) { - if (parent) { - d->parent = parent; - d->parent->d_func()->children.append(this); + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + if (d->isWidget) { + if (parent) { + d->parent = parent; + d->parent->d_func()->children.append(this); + } + // no events sent here, this is done at the end of the QWidget constructor + } else { + setParent(parent); } - // no events sent here, this is done at the end of the QWidget constructor - } else { - setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; } - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; } qt_addObject(this); } @@ -820,7 +805,7 @@ QObject::~QObject() d->wasDeleted = true; d->blockSig = 0; // unblock signals so we always emit destroyed() - if (!d->isWidget) { + if (d->hasGuards && !d->isWidget) { // set all QPointers for this object to zero - note that // ~QWidget() does this for us, so we don't have to do it twice QObjectPrivate::clearGuards(this); @@ -838,22 +823,16 @@ QObject::~QObject() delete d->sharedRefcount; } - QT_TRY { - emit destroyed(this); - } QT_CATCH(...) { - // all the signal/slots connections are still in place - if we don't - // quit now, we will crash pretty soon. - qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); -#if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS) - struct AutotestException : public std::exception - { - const char *what() const throw() { return "autotest swallow"; } - } autotestException; - // throw autotestException; -#else - QT_RETHROW; -#endif + if (d->isSignalConnected(0)) { + QT_TRY { + emit destroyed(this); + } QT_CATCH(...) { + // all the signal/slots connections are still in place - if we don't + // quit now, we will crash pretty soon. + qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); + QT_RETHROW; + } } if (d->declarativeData) @@ -891,7 +870,7 @@ QObject::~QObject() if (c->next) c->next->prev = c->prev; } if (needToUnlock) - m->unlock(); + m->unlockInline(); connectionList.first = c->nextConnectionList; delete c; @@ -915,7 +894,7 @@ QObject::~QObject() bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { - m->unlock(); + m->unlockInline(); continue; } node->receiver = 0; @@ -925,7 +904,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlock(); + m->unlockInline(); } } @@ -935,12 +914,6 @@ QObject::~QObject() d->threadData->eventDispatcher->unregisterTimers(this); } -#ifdef QT3_SUPPORT - d->pendingChildInsertedEvents.clear(); -#endif - - d->eventFilters.clear(); - if (!d->children.isEmpty()) d->deleteChildren(); @@ -1196,7 +1169,9 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { +#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false; +#endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast<QObject*>(mce->sender()); @@ -1514,11 +1489,14 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData currentSender->ref = 0; currentSender = 0; +#ifdef QT_JAMBI_BUILD // the current event thread also shouldn't restore the delete watch inEventHandler = false; + if (deleteWatch) *deleteWatch = 1; deleteWatch = 0; +#endif // set new thread data targetData->ref(); @@ -1768,11 +1746,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11 - \warning This function is not available with MSVC 6. Use - qFindChild() instead if you need to support that version of the - compiler. - - \sa findChildren(), qFindChild() + \sa findChildren() */ /*! @@ -1792,11 +1766,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13 - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. - - \sa findChild(), qFindChildren() + \sa findChild() */ /*! @@ -1807,20 +1777,19 @@ QObjectList QObject::queryList(const char *inheritsClass, and that have names matching the regular expression \a regExp, or an empty list if there are no such objects. The search is performed recursively. - - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. */ /*! \fn T qFindChild(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1828,11 +1797,14 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \fn QList<T> qFindChildren(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1843,9 +1815,13 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QObject::findChildren() */ /*! @@ -1855,9 +1831,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1869,9 +1847,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1991,12 +1971,14 @@ void QObjectPrivate::setParent_helper(QObject *o) QChildEvent e(QEvent::ChildAdded, q); QCoreApplication::sendEvent(parent, &e); #ifdef QT3_SUPPORT - if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { - QCoreApplication::postEvent(parent, - new QEvent(QEvent::ChildInsertedRequest), - Qt::HighEventPriority); + if (QCoreApplicationPrivate::useQt3Support) { + if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { + QCoreApplication::postEvent(parent, + new QEvent(QEvent::ChildInsertedRequest), + Qt::HighEventPriority); + } + parent->d_func()->pendingChildInsertedEvents.append(q); } - parent->d_func()->pendingChildInsertedEvents.append(q); #endif } } @@ -2305,7 +2287,7 @@ static void err_info_about_objects(const char * func, a thread different from this object's thread. Do not use this function in this type of scenario. - \sa QSignalMapper + \sa senderSignalIndex(), QSignalMapper */ QObject *QObject::sender() const @@ -2316,13 +2298,53 @@ QObject *QObject::sender() const if (!d->currentSender) return 0; - // Return 0 if d->currentSender isn't in d->senders - bool found = false; - for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) - found = (c->sender == d->currentSender->sender); - if (!found) - return 0; - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->sender; + } + + return 0; +} + +/*! + \since 4.8 + + Returns the meta-method index of the signal that called the currently + executing slot, which is a member of the class returned by sender(). + If called outside of a slot activated by a signal, -1 is returned. + + For signals with default parameters, this function will always return + the index with all parameters, regardless of which was used with + connect(). For example, the signal \c {destroyed(QObject *obj = 0)} + will have two different indexes (with and without the parameter), but + this function will always return the index with a parameter. This does + not apply when overloading signals with different parameters. + + \warning This function violates the object-oriented principle of + modularity. However, getting access to the signal index might be useful + when many signals are connected to a single slot. + + \warning The return value of this function is not valid when the slot + is called via a Qt::DirectConnection from a thread different from this + object's thread. Do not use this function in this type of scenario. + + \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method() +*/ + +int QObject::senderSignalIndex() const +{ + Q_D(const QObject); + + QMutexLocker locker(signalSlotLock(this)); + if (!d->currentSender) + return -1; + + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->signal; + } + + return -1; } /*! @@ -2384,6 +2406,71 @@ int QObject::receivers(const char *signal) const } /*! + \internal + + This helper function calculates signal and method index for the given + member in the specified class. + + \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1. + + \li If specified member is not a member of obj instance class (or one of + its parent classes) then both signalIndex and methodIndex are set to -1. + + This function is used by QObject::connect and QObject::disconnect which + are working with QMetaMethod. + + \param[out] signalIndex is set to the signal index of member. If the member + specified is not signal this variable is set to -1. + + \param[out] methodIndex is set to the method index of the member. If the + member is not a method of the object specified by obj param this variable + is set to -1. +*/ +void QMetaObjectPrivate::memberIndexes(const QObject *obj, + const QMetaMethod &member, + int *signalIndex, int *methodIndex) +{ + *signalIndex = -1; + *methodIndex = -1; + if (!obj || !member.mobj) + return; + const QMetaObject *m = obj->metaObject(); + // Check that member is member of obj class + while (m != 0 && m != member.mobj) + m = m->d.superdata; + if (!m) + return; + *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5; + + int signalOffset; + int methodOffset; + computeOffsets(m, &signalOffset, &methodOffset); + + *methodIndex += methodOffset; + if (member.methodType() == QMetaMethod::Signal) { + *signalIndex = originalClone(m, *signalIndex); + *signalIndex += signalOffset; + } else { + *signalIndex = -1; + } +} + +static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal, + const QMetaObject *receiver, const QMetaMethod &method) +{ + if (signal.attributes() & QMetaMethod::Compatibility) { + if (!(method.attributes() & QMetaMethod::Compatibility)) + qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", + sender->className(), signal.signature()); + } else if ((method.attributes() & QMetaMethod::Compatibility) && + method.methodType() == QMetaMethod::Signal) { + qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", + sender->className(), signal.signature(), + receiver->className(), method.signature()); + } +} + +/*! \threadsafe Creates a connection of the given \a type from the \a signal in @@ -2560,7 +2647,7 @@ bool QObject::connect(const QObject *sender, const char *signal, } int *types = 0; - if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) + if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes()))) return false; @@ -2568,15 +2655,8 @@ bool QObject::connect(const QObject *sender, const char *signal, { QMetaMethod smethod = smeta->method(signal_absolute_index); QMetaMethod rmethod = rmeta->method(method_index); - if (warnCompat) { - if(smethod.attributes() & QMetaMethod::Compatibility) { - if (!(rmethod.attributes() & QMetaMethod::Compatibility)) - qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal); - } else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) { - qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", - smeta->className(), signal, rmeta->className(), method); - } - } + if (warnCompat) + check_and_warn_compat(smeta, smethod, rmeta, rmethod); } #endif if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) @@ -2585,6 +2665,111 @@ bool QObject::connect(const QObject *sender, const char *signal, return true; } +/*! + \since 4.8 + + Creates a connection of the given \a type from the \a signal in + the \a sender object to the \a method in the \a receiver object. + Returns true if the connection succeeds; otherwise returns false. + + This function works in the same way as + connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + but it uses QMetaMethod to specify signal and method. + + \see connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + */ +bool QObject::connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type) +{ +#ifndef QT_NO_DEBUG + bool warnCompat = true; +#endif + if (type == Qt::AutoCompatConnection) { + type = Qt::AutoConnection; +#ifndef QT_NO_DEBUG + warnCompat = false; +#endif + } + + if (sender == 0 + || receiver == 0 + || signal.methodType() != QMetaMethod::Signal + || method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::connect: Cannot connect %s::%s to %s::%s", + sender ? sender->metaObject()->className() : "(null)", + signal.signature(), + receiver ? receiver->metaObject()->className() : "(null)", + method.signature() ); + return false; + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + + { + QByteArray methodSignature; + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + + const QMetaObject *smeta = sender->metaObject(); + const QMetaObject *rmeta = receiver->metaObject(); + if (signal_index == -1) { + qWarning("QObject::connect: Can't find signal %s on instance of class %s", + signal.signature(), smeta->className()); + return false; + } + if (method_index == -1) { + qWarning("QObject::connect: Can't find method %s on instance of class %s", + method.signature(), rmeta->className()); + return false; + } + + if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) { + qWarning("QObject::connect: Incompatible sender/receiver arguments" + "\n %s::%s --> %s::%s", + smeta->className(), signal.signature(), + rmeta->className(), method.signature()); + return false; + } + + int *types = 0; + if ((type == Qt::QueuedConnection) + && !(types = queuedConnectionTypes(signal.parameterTypes()))) + return false; + +#ifndef QT_NO_DEBUG + if (warnCompat) + check_and_warn_compat(smeta, signal, rmeta, method); +#endif + if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) + return false; + + const_cast<QObject*>(sender)->connectNotify(signalSignature.constData()); + return true; +} /*! \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const @@ -2764,6 +2949,107 @@ bool QObject::disconnect(const QObject *sender, const char *signal, return res; } +/*! + \since 4.8 + + Disconnects \a signal in object \a sender from \a method in object + \a receiver. Returns true if the connection is successfully broken; + otherwise returns false. + + This function provides the same posibilities like + disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + but uses QMetaMethod to represent the signal and the method to be disconnected. + + Additionally this function returnsfalse and no signals and slots disconnected + if: + \list 1 + + \i \a signal is not a member of sender class or one of its parent classes. + + \i \a method is not a member of receiver class or one of its parent classes. + + \i \a signal instance represents not a signal. + + \endlist + + QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object". + In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case + method shoud also be QMetaMethod(). \a sender parameter should be never 0. + + \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + */ +bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method) +{ + if (sender == 0 || (receiver == 0 && method.mobj != 0)) { + qWarning("Object::disconnect: Unexpected null parameter"); + return false; + } + if (signal.mobj) { + if(signal.methodType() != QMetaMethod::Signal) { + qWarning("Object::%s: Attempt to %s non-signal %s::%s", + "disconnect","unbind", + sender->metaObject()->className(), signal.signature()); + return false; + } + } + if (method.mobj) { + if(method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::disconect: cannot use constructor as argument %s::%s", + receiver->metaObject()->className(), method.signature()); + return false; + } + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + if (signal.mobj) { + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + } + + { + QByteArray methodSignature; + if (method.mobj) { + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + } + const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0, + receiver, method.mobj ? methodSignature.constData() : 0 }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + // If we are here sender is not null. If signal is not null while signal_index + // is -1 then this signal is not a member of sender. + if (signal.mobj && signal_index == -1) { + qWarning("QObject::disconect: signal %s not found on class %s", + signal.signature(), sender->metaObject()->className()); + return false; + } + // If this condition is true then method is not a member of receeiver. + if (receiver && method.mobj && method_index == -1) { + qWarning("QObject::disconect: method %s not found on class %s", + method.signature(), receiver->metaObject()->className()); + return false; + } + + if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index)) + return false; + + const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0); + return true; +} /*! \threadsafe @@ -2981,7 +3267,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlock(); + receiverMutex->unlockInline(); c->receiver = 0; @@ -3068,7 +3354,7 @@ void QMetaObject::connectSlotsByName(QObject *o) return; const QMetaObject *mo = o->metaObject(); Q_ASSERT(mo); - const QObjectList list = qFindChildren<QObject *>(o, QString()); + const QObjectList list = o->findChildren<QObject *>(QString()); for (int i = 0; i < mo->methodCount(); ++i) { const char *slot = mo->method(i).signature(); Q_ASSERT(slot); @@ -3115,8 +3401,7 @@ void QMetaObject::connectSlotsByName(QObject *o) } } -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, - void **argv, QSemaphore *semaphore = 0) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) { QMetaMethod m = sender->metaObject()->method(signal); @@ -3146,30 +3431,9 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect signal, nargs, types, - args, - semaphore)); + args)); } -static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) -{ - if (QThread::currentThread() == c->receiver->thread()) { - qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " - "Sender is %s(%p), receiver is %s(%p)", - sender->metaObject()->className(), sender, - c->receiver->metaObject()->className(), c->receiver); - } - -#ifdef QT_NO_THREAD - queued_activate(sender, signal, c, argv); -#else - QSemaphore semaphore; - queued_activate(sender, signal, c, argv, &semaphore); - QMutex *mutex = signalSlotLock(sender); - mutex->unlock(); - semaphore.acquire(); - mutex->lock(); -#endif -} /*!\internal \obsolete. @@ -3233,23 +3497,38 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign continue; QObject * const receiver = c->receiver; + const int method = c->method; + const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; // determine if this connection should be sent immediately or // put into the event queue if ((c->connectionType == Qt::AutoConnection - && (currentThreadData != sender->d_func()->threadData + && (!receiverInSameThread || receiver->d_func()->threadData != sender->d_func()->threadData)) || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); continue; +#ifndef QT_NO_THREAD } else if (c->connectionType == Qt::BlockingQueuedConnection) { - blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); + locker.unlock(); + if (receiverInSameThread) { + qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " + "Sender is %s(%p), receiver is %s(%p)", + sender->metaObject()->className(), sender, + receiver->metaObject()->className(), receiver); + } + QSemaphore semaphore; + QCoreApplication::postEvent(receiver, new QMetaCallEvent(method, + sender, signal_absolute_index, + 0, 0, + argv ? argv : empty_argv, + &semaphore)); + semaphore.acquire(); + locker.relock(); continue; +#endif } - - const int method = c->method; QObjectPrivate::Sender currentSender; - const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; QObjectPrivate::Sender *previousSender = 0; if (receiverInSameThread) { currentSender.sender = sender; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1b613a6..b5db936 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -77,19 +77,9 @@ class QObjectUserData; typedef QList<QObject*> QObjectList; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template<typename T> inline T qFindChild(const QObject *o, const QString &name = QString(), T = 0); -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QString &name = QString(), T = 0); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T = 0); -# endif -#else -template<typename T> inline T qFindChild(const QObject *, const QString & = QString()); -template<typename T> inline QList<T> qFindChildren(const QObject *, const QString & = QString()); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *, const QRegExp &); -# endif -#endif +Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, + const QMetaObject &mo, QList<void *> *list); +Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); class #if defined(__INTEL_COMPILER) && defined(Q_OS_WIN) @@ -109,7 +99,7 @@ public: uint ownObjectName : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; - uint inEventHandler : 1; + uint inEventHandler : 1; //only used if QT_JAMBI_BUILD uint inThreadChangeEvent : 1; uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; @@ -164,20 +154,36 @@ public: int startTimer(int interval); void killTimer(int id); -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline T findChild(const QString &aName = QString()) const - { return qFindChild<T>(this, aName); } + { return static_cast<T>(qt_qFindChild_helper(this, aName, reinterpret_cast<T>(0)->staticMetaObject)); } template<typename T> inline QList<T> findChildren(const QString &aName = QString()) const - { return qFindChildren<T>(this, aName); } + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, aName, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #ifndef QT_NO_REGEXP template<typename T> inline QList<T> findChildren(const QRegExp &re) const - { return qFindChildren<T>(this, re); } -#endif + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #endif #ifdef QT3_SUPPORT @@ -207,6 +213,21 @@ public: #endif #endif ); + + static bool connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type = +#ifdef qdoc + Qt::AutoConnection +#else +#ifdef QT3_SUPPORT + Qt::AutoCompatConnection +#else + Qt::AutoConnection +#endif +#endif + ); + inline bool connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = #ifdef qdoc @@ -222,6 +243,8 @@ public: static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member); + static bool disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &member); inline bool disconnect(const char *signal = 0, const QObject *receiver = 0, const char *member = 0) { return disconnect(this, signal, receiver, member); } @@ -257,6 +280,7 @@ public Q_SLOTS: protected: QObject *sender() const; + int senderSignalIndex() const; int receivers(const char* signal) const; virtual void timerEvent(QTimerEvent *); @@ -321,135 +345,31 @@ public: }; #endif -Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, - const QMetaObject &mo, QList<void *> *list); -Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); - -#if defined Q_CC_MSVC && _MSC_VER < 1300 - +#ifdef QT_DEPRECATED template<typename T> -inline T qFindChild(const QObject *o, const QString &name, T) -{ return static_cast<T>(qt_qFindChild_helper(o, name, ((T)0)->staticMetaObject)); } +inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) +{ return o->findChild<T>(name); } template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name, T) +inline QList<T> qFindChildren(const QObject *o, const QString &name = QString()) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, name, 0, ((T)0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(name); } -template<typename T> -inline T qFindChild(const QObject *o, const QString &name) -{ return qFindChild<T>(o, name, T(0)); } - -template<typename T> -inline T qFindChild(const QObject *o) -{ return qFindChild<T>(o, QString(), T(0)); } - -template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name) -{ return qFindChildren<T>(o, name, T(0)); } - -template<typename T> -inline QList<T> qFindChildren(const QObject *o) -{ return qFindChildren<T>(o, QString(), T(0)); } - #ifndef QT_NO_REGEXP template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, 0, &re, ((T)0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(re); } - -template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) -{ return qFindChildren<T>(o, re, T(0)); } - #endif -#ifdef Q_MOC_RUN -# define Q_DECLARE_INTERFACE(IFace, IId) Q_DECLARE_INTERFACE(IFace, IId) -#endif // Q_MOC_RUN - - -template <class T> inline const char * qobject_interface_iid() -{ return 0; } - -template <class T> inline T qobject_cast_helper(QObject *object, T) -{ return static_cast<T>(((T)0)->staticMetaObject.cast(object)); } - -template <class T> inline T qobject_cast_helper(const QObject *object, T) -{ return static_cast<T>(const_cast<const QObject *>(((T)0)->staticMetaObject.cast(const_cast<QObject *>(object)))); } - -template <class T> -inline T qobject_cast(QObject *object) -{ return qobject_cast_helper<T>(object, T(0)); } - -template <class T> -inline T qobject_cast(const QObject *object) -{ return qobject_cast_helper<T>(object, T(0)); } - -#ifndef Q_MOC_RUN -# define Q_DECLARE_INTERFACE(IFace, IId) \ - template <> inline const char *qobject_interface_iid<IFace *>() \ - { return IId; } \ - template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \ - { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \ - template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \ - { return (IFace *)(object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0); } -#endif // Q_MOC_RUN - -#else - -template<typename T> -inline T qFindChild(const QObject *o, const QString &name) -{ return static_cast<T>(qt_qFindChild_helper(o, name, reinterpret_cast<T>(0)->staticMetaObject)); } - -template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name) -{ - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, name, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; -} - -#ifndef QT_NO_REGEXP -template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) -{ - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; -} -#endif +#endif //QT_DEPRECATED template <class T> inline T qobject_cast(QObject *object) { -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object)); #endif return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); @@ -462,7 +382,7 @@ inline T qobject_cast(const QObject *object) register T ptr = static_cast<T>(object); Q_UNUSED(ptr); -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object))); #endif return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object)))); @@ -482,8 +402,6 @@ template <class T> inline const char * qobject_interface_iid() { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); } #endif // Q_MOC_RUN -#endif - #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); #endif diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 4800e6a..82023d4 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -55,6 +55,7 @@ #include "QtCore/qobject.h" #include "QtCore/qpointer.h" +#include "QtCore/qsharedpointer.h" #include "QtCore/qcoreevent.h" #include "QtCore/qlist.h" #include "QtCore/qvector.h" @@ -153,7 +154,6 @@ public: #ifdef QT3_SUPPORT void sendPendingChildInsertedEvents(); - void removePendingChildInsertedEvents(QObject *child); #endif static inline Sender *setCurrentSender(QObject *receiver, @@ -161,8 +161,10 @@ public: static inline void resetCurrentSender(QObject *receiver, Sender *currentSender, Sender *previousSender); +#ifdef QT_JAMBI_BUILD static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); +#endif static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { @@ -184,7 +186,7 @@ public: mutable quint32 connectedSignals[2]; #ifdef QT3_SUPPORT - QList<QObject *> pendingChildInsertedEvents; + QVector< QWeakPointer<QObject> > pendingChildInsertedEvents; #else // preserve binary compatibility with code compiled without Qt 3 support // keeping the binary layout stable helps the Qt Creator debugger @@ -200,7 +202,9 @@ public: // these objects are all used to indicate that a QObject was deleted // plus QPointer, which keeps a separate list QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; +#ifdef QT_JAMBI_BUILD int *deleteWatch; +#endif }; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 555a1f5..996fce2 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -117,7 +117,7 @@ class QString; # define QT_TR_FUNCTIONS #endif -#if defined(QT_NO_MEMBER_TEMPLATES) || defined(QT_NO_QOBJECT_CHECK) +#if defined(QT_NO_QOBJECT_CHECK) /* tmake ignore Q_OBJECT */ #define Q_OBJECT_CHECK #else @@ -144,7 +144,7 @@ inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; } template <typename T1, typename T2> inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {} -#endif // QT_NO_MEMBER_TEMPLATES +#endif // QT_NO_QOBJECT_CHECK #ifdef Q_NO_DATA_RELOCATION #define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject(); diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index fe93ebc..0782ffe 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -142,9 +142,12 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, remain. Do not mix using QtSharedMemory and QSharedMemory. Port everything to QSharedMemory. - \warning QSharedMemory changes the key in a Qt-specific way. - It is therefore currently not possible to use the shared memory of - non-Qt applications with QSharedMemory. + \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise + specified. Interoperation with non-Qt applications is achieved by first creating + a default shared memory with QSharedMemory() and then setting a native key with + setNativeKey(). When using native keys, shared memory is not protected against + multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism + should be used to achieve a such protection. */ /*! @@ -153,8 +156,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, Constructs a shared memory object with the given \a parent. The shared memory object's key is not set by the constructor, so the shared memory object does not have an underlying shared memory - segment attached. The key must be set with setKey() before create() - or attach() can be used. + segment attached. The key must be set with setKey() or setNativeKey() + before create() or attach() can be used. \sa setKey() */ @@ -191,24 +194,62 @@ QSharedMemory::~QSharedMemory() } /*! - Sets a new \a key for this shared memory object. If \a key and the - current key are the same, the function returns without doing - anything. If the shared memory object is attached to an underlying - shared memory segment, it will \l {detach()} {detach} from it before - setting the new key. This function does not do an attach(). + Sets the platform independent \a key for this shared memory object. If \a key + is the same as the current key, the function returns without doing anything. - \sa key() isAttached() - */ + You can call key() to retrieve the platform independent key. Internally, + QSharedMemory converts this key into a platform specific key. If you instead + call nativeKey(), you will get the platform specific, converted key. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + \sa key() nativeKey() isAttached() +*/ void QSharedMemory::setKey(const QString &key) { Q_D(QSharedMemory); - if (key == d->key) + if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey) return; if (isAttached()) detach(); d->cleanHandle(); d->key = key; + d->nativeKey = d->makePlatformSafeKey(key); +} + +/*! + \since 4.8 + + Sets the native, platform specific, \a key for this shared memory object. If + \a key is the same as the current native key, the function returns without + doing anything. If all you want is to assign a key to a segment, you should + call setKey() instead. + + You can call nativeKey() to retrieve the native key. If a native key has been + assigned, calling key() will return a null string. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + The application will not be portable if you set a native key. + + \sa nativeKey() key() isAttached() +*/ +void QSharedMemory::setNativeKey(const QString &key) +{ + Q_D(QSharedMemory); + if (key == d->nativeKey && d->key.isNull()) + return; + + if (isAttached()) + detach(); + d->cleanHandle(); + d->key = QString(); + d->nativeKey = key; } bool QSharedMemoryPrivate::initKey() @@ -251,13 +292,15 @@ bool QSharedMemoryPrivate::initKey() } /*! - Returns the key assigned to this shared memory. The key is the - identifier used by the operating system to identify the shared - memory segment. When QSharedMemory is used for interprocess - communication, the key is how each process attaches to the shared - memory segment through which the IPC occurs. + Returns the key assigned with setKey() to this shared memory, or a null key + if no key has been assigned, or if the segment is using a nativeKey(). The + key is the identifier used by Qt applications to identify the shared memory + segment. + + You can find the native, platform specific, key used by the operating system + by calling nativeKey(). - \sa setKey() + \sa setKey() setNativeKey() */ QString QSharedMemory::key() const { @@ -266,13 +309,30 @@ QString QSharedMemory::key() const } /*! - Creates a shared memory segment of \a size bytes with the key passed - to the constructor or set with setKey(), attaches to the new shared - memory segment with the given access \a mode, and returns \tt true. - If a shared memory segment identified by the key already exists, the - attach operation is not performed, and \tt false is returned. When - the return value is \tt false, call error() to determine which error - occurred. + \since 4.8 + + Returns the native, platform specific, key for this shared memory object. The + native key is the identifier used by the operating system to identify the + shared memory segment. + + You can use the native key to access shared memory segments that have not + been created by Qt, or to grant shared memory access to non-Qt applications. + + \sa setKey() setNativeKey() +*/ +QString QSharedMemory::nativeKey() const +{ + Q_D(const QSharedMemory); + return d->nativeKey; +} + +/*! + Creates a shared memory segment of \a size bytes with the key passed to the + constructor, set with setKey() or set with setNativeKey(), then attaches to + the new shared memory segment with the given access \a mode and returns + \tt true. If a shared memory segment identified by the key already exists, + the attach operation is not performed and \tt false is returned. When the + return value is \tt false, call error() to determine which error occurred. \sa error() */ @@ -294,7 +354,7 @@ bool QSharedMemory::create(int size, AccessMode mode) QString function = QLatin1String("QSharedMemory::create"); #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, function)) + if (!d->key.isNull() && !d->tryLocker(&lock, function)) return false; #endif @@ -338,7 +398,7 @@ int QSharedMemory::size() const /*! Attempts to attach the process to the shared memory segment identified by the key that was passed to the constructor or to a - call to setKey(). The access \a mode is \l {QSharedMemory::} + call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::} {ReadWrite} by default. It can also be \l {QSharedMemory::} {ReadOnly}. Returns true if the attach operation is successful. If false is returned, call error() to determine which error occurred. @@ -355,7 +415,7 @@ bool QSharedMemory::attach(AccessMode mode) return false; #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) return false; #endif @@ -395,7 +455,7 @@ bool QSharedMemory::detach() #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) return false; #endif @@ -451,9 +511,9 @@ const void *QSharedMemory::data() const by this process and returns true. If another process has locked the segment, this function blocks until the lock is released. Then it acquires the lock and returns true. If this function returns false, - it means either that you have ignored a false return from create() - or attach(), or that QSystemSemaphore::acquire() failed due to an - unknown system error. + it means that you have ignored a false return from create() or attach(), + that you have set the key with setNativeKey() or that + QSystemSemaphore::acquire() failed due to an unknown system error. \sa unlock(), data(), QSystemSemaphore::acquire() */ diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h index fba939c..5673f43 100644 --- a/src/corelib/kernel/qsharedmemory.h +++ b/src/corelib/kernel/qsharedmemory.h @@ -85,6 +85,8 @@ public: void setKey(const QString &key); QString key() const; + void setNativeKey(const QString &key); + QString nativeKey() const; bool create(int size, AccessMode mode = ReadWrite); int size() const; diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index a52f8b3..632a6e9 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -122,6 +122,7 @@ public: void *memory; int size; QString key; + QString nativeKey; QSharedMemory::SharedMemoryError error; QString errorString; #ifndef QT_NO_SYSTEMSEMAPHORE diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp index 9b84eb56..091c2b5 100644 --- a/src/corelib/kernel/qsharedmemory_symbian.cpp +++ b/src/corelib/kernel/qsharedmemory_symbian.cpp @@ -107,16 +107,14 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = chunk.CreateGlobal(ptr, size, size); @@ -136,14 +134,13 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */) // Grab a pointer to the memory block if (!chunk.Handle()) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = KErrNoMemory; diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index a5f79c2..064979b 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -116,21 +116,20 @@ key_t QSharedMemoryPrivate::handle() return unix_key; // don't allow making handles on empty keys - if (key.isEmpty()) { + if (nativeKey.isEmpty()) { errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; return 0; } // ftok requires that an actual file exists somewhere - QString fileName = makePlatformSafeKey(key); - if (!QFile::exists(fileName)) { + if (!QFile::exists(nativeKey)) { errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::NotFound; return 0; } - unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q'); if (-1 == unix_key) { errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -181,7 +180,7 @@ bool QSharedMemoryPrivate::create(int size) { // build file if needed bool createdFile = false; - int built = createUnixKeyFile(makePlatformSafeKey(key)); + int built = createUnixKeyFile(nativeKey); if (built == -1) { errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -194,7 +193,7 @@ bool QSharedMemoryPrivate::create(int size) // get handle if (!handle()) { if (createdFile) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -210,7 +209,7 @@ bool QSharedMemoryPrivate::create(int size) setErrorString(function); } if (createdFile && error != QSharedMemory::AlreadyExists) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -295,7 +294,7 @@ bool QSharedMemoryPrivate::detach() } // remove file - if (!QFile::remove(makePlatformSafeKey(key))) + if (!QFile::remove(nativeKey)) return false; } return true; diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index 0f5fdc7..0cdb123 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -99,18 +99,17 @@ HANDLE QSharedMemoryPrivate::handle() { if (!hand) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } #ifndef Q_OS_WINCE - hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)safeKey.utf16()); + hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16()); #else // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16()); #endif if (!hand) { setErrorString(function); @@ -133,17 +132,15 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } // Create the file mapping. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16()); setErrorString(function); // hand is valid when it already exists unlike unix so explicitly check diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f5d7c0d..feb85ce 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -947,11 +947,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (double)(qlonglong)qMetaTypeUNumber(d); -#else *f = double(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0; @@ -986,11 +982,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (float)(qlonglong)qMetaTypeUNumber(d); -#else *f = float(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0f; @@ -1084,7 +1076,7 @@ static void streamDebug(QDebug dbg, const QVariant &v) dbg.nospace() << v.toFloat(); break; case QMetaType::QObjectStar: - dbg.nospace() << qVariantValue<QObject *>(v); + dbg.nospace() << qvariant_cast<QObject *>(v); break; case QVariant::Double: dbg.nospace() << v.toDouble(); @@ -1245,7 +1237,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; conversion functions to data types defined in QtGui, such as QColor, QImage, and QPixmap. In other words, there is no \c toColor() function. Instead, you can use the QVariant::value() or - the qVariantValue() template function. For example: + the qvariant_cast() template function. For example: \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2 @@ -1360,12 +1352,12 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; Note that you have to pass the address of the variable you want stored. - Usually, you never have to use this constructor, use qVariantFromValue() + Usually, you never have to use this constructor, use QVariant::fromValue() instead to construct variants from the pointer types represented by \c QMetaType::VoidStar, \c QMetaType::QObjectStar and \c QMetaType::QWidgetStar. - \sa qVariantFromValue(), Type + \sa QVariant::fromValue(), Type */ /*! @@ -3074,10 +3066,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4 - \warning This function is not available with MSVC 6. Use - qVariantSetValue() instead if you need to support that version of - the compiler. - \sa value(), fromValue(), canConvert() */ @@ -3095,10 +3083,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5 - \warning This function is not available with MSVC 6. Use - qVariantValue() or qvariant_cast() instead if you need to support - that version of the compiler. - \sa setValue(), fromValue(), canConvert() */ @@ -3111,10 +3095,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6 - \warning This function is not available with MSVC 6. Use - qVariantCanConvert() instead if you need to support that version - of the compiler. - \sa convert() */ @@ -3130,23 +3110,22 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \note If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type. - \warning This function is not available with MSVC 6. Use - qVariantFromValue() instead if you need to support that version - of the compiler. - \sa setValue(), value() */ /*! \fn QVariant qVariantFromValue(const T &value) \relates QVariant + \obsolete Returns a variant containing a copy of the given \a value with template type \c{T}. - This function is equivalent to QVariant::fromValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::fromValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. For example, a QObject pointer can be stored in a variant with the following code: @@ -3158,13 +3137,16 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) /*! \fn void qVariantSetValue(QVariant &variant, const T &value) \relates QVariant + \obsolete Sets the contents of the given \a variant to a copy of the \a value with the specified template type \c{T}. - This function is equivalent to QVariant::setValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::setValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::setValue() */ @@ -3175,33 +3157,39 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Returns the given \a value converted to the template type \c{T}. - This function is equivalent to qVariantValue(). + This function is equivalent to QVariant::value(). - \sa qVariantValue(), QVariant::value() + \sa QVariant::value() */ /*! \fn T qVariantValue(const QVariant &value) \relates QVariant + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to - \l{QVariant::value()}{QVariant::value}<T>(\a value). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \l{QVariant::value()}{QVariant::value}<T>(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::value(), qvariant_cast() */ /*! \fn bool qVariantCanConvert(const QVariant &value) \relates QVariant + \obsolete Returns true if the given \a value can be converted to the template type specified; otherwise returns false. - This function is equivalent to QVariant::canConvert(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::canConvert(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::canConvert() */ diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index cb2825c..a4d45f6 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -83,19 +83,11 @@ class QUrl; class QVariant; class QVariantComparisonHelper; -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QVariant qVariantFromValue(const T &); -template <typename T> -inline void qVariantSetValue(QVariant &, const T &); - -template<typename T> -inline T qVariantValue(const QVariant &); - template<typename T> -inline bool qVariantCanConvert(const QVariant &); -#endif +inline T qvariant_cast(const QVariant &); class Q_CORE_EXPORT QVariant { @@ -327,13 +319,12 @@ class Q_CORE_EXPORT QVariant const void *constData() const; inline const void *data() const { return constData(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void setValue(const T &value); template<typename T> inline T value() const - { return qVariantValue<T>(*this); } + { return qvariant_cast<T>(*this); } template<typename T> static inline QVariant fromValue(const T &value) @@ -341,8 +332,7 @@ class Q_CORE_EXPORT QVariant template<typename T> bool canConvert() const - { return qVariantCanConvert<T>(*this); } -#endif + { return canConvert(Type(qMetaTypeId<T>())); } public: #ifndef qdoc @@ -527,11 +517,9 @@ inline QSize &QVariant::asSize() { return *reinterpret_cast<QSize *>(castOrDetach(Size)); } #endif //QT3_SUPPORT -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void QVariant::setValue(const T &avalue) { qVariantSetValue(*this, avalue); } -#endif #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); @@ -594,16 +582,16 @@ template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) return v; } +#ifdef QT_DEPRECATED template<typename T> -inline T qVariantValue(const QVariant &variant) +inline QT_DEPRECATED T qVariantValue(const QVariant &variant) { return qvariant_cast<T>(variant); } template<typename T> -inline bool qVariantCanConvert(const QVariant &variant) -{ - return variant.canConvert(static_cast<QVariant::Type>( - qMetaTypeId<T>(static_cast<T *>(0)))); -} +inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) +{ return variant.template canConvert<T>(); } +#endif + #endif Q_DECLARE_SHARED(QVariant) Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE); diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 0f99948..f6ae038 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -426,10 +426,14 @@ struct LibraryData { LibraryData() : settings(0) { } ~LibraryData() { delete settings; + foreach(QLibraryPrivate *lib, loadedLibs) { + lib->unload(); + } } QSettings *settings; LibraryMap libraryMap; + QSet<QLibraryPrivate*> loadedLibs; }; Q_GLOBAL_STATIC(LibraryData, libraryData) @@ -481,7 +485,18 @@ bool QLibraryPrivate::load() return true; if (fileName.isEmpty()) return false; - return load_sys(); + + bool ret = load_sys(); + if (ret) { + //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted + //this allows to unload the library at a later time + if (LibraryData *lib = libraryData()) { + lib->loadedLibs += this; + libraryRefCount.ref(); + } + } + + return ret; } bool QLibraryPrivate::unload() @@ -489,10 +504,16 @@ bool QLibraryPrivate::unload() if (!pHnd) return false; if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); + delete inst.data(); if (unload_sys()) { - instance = 0; + if (qt_debug_component()) + qWarning() << "QLibraryPrivate::unload succeeded on" << fileName; + //when the library is unloaded, we release the reference on it so that 'this' + //can get deleted + if (LibraryData *lib = libraryData()) { + if (lib->loadedLibs.remove(this)) + libraryRefCount.deref(); + } pHnd = 0; } } @@ -534,7 +555,7 @@ bool QLibraryPrivate::loadPlugin() \table \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll + \row \i Windows \i \c .dll, \c .DLL \row \i Unix/Linux \i \c .so \row \i AIX \i \c .a \row \i HP-UX \i \c .sl, \c .so (HP-UXi) @@ -547,7 +568,7 @@ bool QLibraryPrivate::loadPlugin() bool QLibrary::isLibrary(const QString &fileName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return fileName.endsWith(QLatin1String(".dll")); + return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive); #elif defined(Q_OS_SYMBIAN) // Plugin stubs are also considered libraries in Symbian. return (fileName.endsWith(QLatin1String(".dll")) || @@ -609,6 +630,46 @@ bool QLibrary::isLibrary(const QString &fileName) } +#if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL) +#define QT_USE_MS_STD_EXCEPTION 1 +const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + typedef const char * (*VerificationFunction)(); + VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn); + __try { + if(func) + szData = func(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + *exceptionThrown = true; + } + return szData; +} +#endif + +#ifdef Q_CC_BOR +typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); +#else +typedef const char * (*QtPluginQueryVerificationDataFunction)(); +#endif + +bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + if (!pfn) + return false; +#ifdef QT_USE_MS_STD_EXCEPTION + szData = qt_try_versioninfo((void *)pfn, exceptionThrown); + if (*exceptionThrown) + return false; +#else + szData = pfn(); +#endif + return qt_parse_pattern(szData, qt_version, debug, key); +} + bool QLibraryPrivate::isPlugin(QSettings *settings) { errorString.clear(); @@ -684,70 +745,82 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) } else #endif { - bool temporary_load = false; + bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases) + do { + bool temporary_load = false; #ifdef Q_OS_WIN - HMODULE hTempModule = 0; + HMODULE hTempModule = 0; #endif - if (!pHnd) { + if (!pHnd) { #ifdef Q_OS_WIN - //avoid 'Bad Image' message box - UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - SetErrorMode(oldmode); + DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES; + //avoid 'Bad Image' message box + UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags); + SetErrorMode(oldmode); #else # if defined(Q_OS_SYMBIAN) - //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists - if (fileinfo.exists()) + //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists + if (fileinfo.exists()) # endif - temporary_load = load_sys(); + temporary_load = load_sys(); #endif - } -# ifdef Q_CC_BOR - typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); -# else - typedef const char * (*QtPluginQueryVerificationDataFunction)(); -# endif + } #ifdef Q_OS_WIN - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule - ? (QtPluginQueryVerificationDataFunction) + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction) #ifdef Q_OS_WINCE - ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") #else - ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") #endif : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); #else - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; # if defined(Q_OS_SYMBIAN) - if (temporary_load) { - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); - // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal - if (!qtPluginQueryVerificationDataFunction) - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); - } + if (temporary_load) { + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal + if (!qtPluginQueryVerificationDataFunction) + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); + } # else - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); # endif #endif - - if (!qtPluginQueryVerificationDataFunction - || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) { - qt_version = 0; - key = "unknown"; - if (temporary_load) - unload_sys(); - } else { - success = true; - } -#ifdef Q_OS_WIN - if (hTempModule) { - BOOL ok = ::FreeLibrary(hTempModule); - if (ok) { - hTempModule = 0; + bool exceptionThrown = false; + bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction, + &qt_version, &debug, &key, &exceptionThrown); + if (!exceptionThrown) { + if (!ret) { + qt_version = 0; + key = "unknown"; + if (temporary_load) + unload_sys(); + } else { + success = true; + } + retryLoadLibrary = false; + } +#ifdef QT_USE_MS_STD_EXCEPTION + else { + // An exception was thrown when calling qt_plugin_query_verification_data(). + // This usually happens when plugin is compiled with the /clr compiler flag, + // & will only work if the dependencies are loaded & DLLMain() is called. + // LoadLibrary() will do this, try once with this & if it fails dont load. + retryLoadLibrary = !retryLoadLibrary; } +#endif +#ifdef Q_OS_WIN + if (hTempModule) { + BOOL ok = ::FreeLibrary(hTempModule); + if (ok) { + hTempModule = 0; + } - } + } #endif + } while(retryLoadLibrary); // Will be 'false' in all cases other than when an + // exception is thrown(will happen only when using a MS compiler) } // Qt 4.5 compatibility: stl doesn't affect binary compatibility @@ -1074,7 +1147,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver */ void *QLibrary::resolve(const char *symbol) { - if (!load()) + if (!isLoaded() && !load()) return 0; return d->resolve(symbol); } diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 02dc523..b73fce5 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -60,6 +60,7 @@ #include "QtCore/qpointer.h" #include "QtCore/qstringlist.h" #include "QtCore/qplugin.h" +#include "QtCore/qsharedpointer.h" #ifndef QT_NO_LIBRARY @@ -90,6 +91,7 @@ public: static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); + QWeakPointer<QObject> inst; QtPluginInstanceFunction instance; uint qt_version; QString lastModified; diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index e8f0eae..9ad1c01 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -223,11 +223,15 @@ bool QLibraryPrivate::load_sys() #ifdef Q_OS_MAC if (!pHnd) { - if (CFBundleRef bundle = CFBundleGetBundleWithIdentifier(QCFString(fileName))) { + QByteArray utf8Bundle = fileName.toUtf8(); + QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); + QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); + if(bundle) { QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - pHnd = dlopen(QFile::encodeName(str), dlFlags); - attempt = str; + char executableFile[FILENAME_MAX]; + CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); + attempt = QString::fromUtf8(executableFile); + pHnd = dlopen(QFile::encodeName(attempt), dlFlags); } } #endif diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index b1d1ecc..9f322df 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -198,11 +198,11 @@ QPluginLoader::~QPluginLoader() */ QObject *QPluginLoader::instance() { - if (!load()) + if (!isLoaded() && !load()) return 0; - if (d->instance) - return d->instance(); - return 0; + if (!d->inst && d->instance) + d->inst = d->instance(); + return d->inst.data(); } /*! diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 9d5c49f..a3c702a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -793,7 +793,7 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } // We require that at least one animation is valid. // ### generalize - QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim); + QList<QVariantAnimation*> variantAnims = anim->findChildren<QVariantAnimation*>(); if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim)) variantAnims.append(va); @@ -1178,7 +1178,7 @@ void QStateMachinePrivate::removeStartState() void QStateMachinePrivate::clearHistory() { Q_Q(QStateMachine); - QList<QHistoryState*> historyStates = qFindChildren<QHistoryState*>(q); + QList<QHistoryState*> historyStates = q->findChildren<QHistoryState*>(); for (int i = 0; i < historyStates.size(); ++i) { QHistoryState *h = historyStates.at(i); QHistoryStatePrivate::get(h)->configuration.clear(); @@ -1440,7 +1440,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState) Q_ASSERT(sourceState != 0); // Reuse previous GoToStateTransition in case of several calls to // goToState() in a row. - GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState); + GoToStateTransition *trans = sourceState->findChild<GoToStateTransition*>(); if (!trans) { trans = new GoToStateTransition(targetState); sourceState->addTransition(trans); @@ -1562,7 +1562,7 @@ void QStateMachinePrivate::unregisterAllTransitions() { Q_Q(QStateMachine); { - QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState()); + QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QSignalTransition *t = transitions.at(i); if (t->machine() == q) @@ -1570,7 +1570,7 @@ void QStateMachinePrivate::unregisterAllTransitions() } } { - QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState()); + QList<QEventTransition*> transitions = rootState()->findChildren<QEventTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QEventTransition *t = transitions.at(i); if (t->machine() == q) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 43df13a..b85a22d 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -130,7 +130,7 @@ QMutex::QMutex(RecursionMode mode) \warning Destroying a locked mutex may result in undefined behavior. */ QMutex::~QMutex() -{ delete d; } +{ delete static_cast<QMutexPrivate *>(d); } /*! Locks the mutex. If another thread has locked the mutex then this @@ -146,6 +146,7 @@ QMutex::~QMutex() */ void QMutex::lock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -158,11 +159,6 @@ void QMutex::lock() bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - // didn't get the lock, wait for it isLocked = d->wait(); Q_ASSERT_X(isLocked, "QMutex::lock", @@ -178,54 +174,11 @@ void QMutex::lock() return; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { - int spinCount = 0; - int lastSpinCount = d->lastSpinCount; - - enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; - const int maximumSpinCount = lastSpinCount + AdditionalSpins; - - do { - if (spinCount++ > maximumSpinCount) { - // puts("spinning useless, sleeping"); - isLocked = d->contenders.fetchAndAddAcquire(1) == 0; - if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - - // didn't get the lock, wait for it - isLocked = d->wait(); - Q_ASSERT_X(isLocked, "QMutex::lock", - "Internal error, infinite wait has timed out."); - - // don't need to wait for the lock anymore - d->contenders.deref(); - } - // decrease the lastSpinCount since we didn't actually get the lock by spinning - spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; - break; - } - - isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); - } while (!isLocked); - - // adjust the last spin lock count - lastSpinCount = d->lastSpinCount; - d->lastSpinCount = spinCount >= 0 - ? qMax(lastSpinCount, spinCount) - : lastSpinCount + spinCount; + lockInternal(); } - -#ifndef QT_NO_DEBUG - d->owner = self; -#endif } /*! @@ -247,6 +200,7 @@ void QMutex::lock() */ bool QMutex::tryLock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -270,18 +224,12 @@ bool QMutex::tryLock() return isLocked; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { // some other thread has the mutex locked, or we tried to // recursively lock an non-recursive mutex return isLocked; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return isLocked; } @@ -310,6 +258,7 @@ bool QMutex::tryLock() */ bool QMutex::tryLock(int timeout) { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -337,9 +286,6 @@ bool QMutex::tryLock(int timeout) return true; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { // didn't get the lock, wait for it @@ -350,9 +296,6 @@ bool QMutex::tryLock(int timeout) if (!isLocked) return false; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return true; } @@ -366,8 +309,7 @@ bool QMutex::tryLock(int timeout) */ void QMutex::unlock() { - Q_ASSERT_X(d->owner == QThread::currentThreadId(), "QMutex::unlock()", - "A mutex must be unlocked in the same thread that locked it."); + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); if (d->recursive) { if (!--d->count) { @@ -376,9 +318,6 @@ void QMutex::unlock() d->wakeUp(); } } else { -#ifndef QT_NO_DEBUG - d->owner = 0; -#endif if (!d->contenders.testAndSetRelease(1, 0)) d->wakeUp(); } @@ -506,6 +445,72 @@ void QMutex::unlock() Use the constructor that takes a RecursionMode parameter instead. */ +/*! + \internal helper for lockInline() + */ +void QMutex::lockInternal() +{ + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); + int spinCount = 0; + int lastSpinCount = d->lastSpinCount; + + enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; + const int maximumSpinCount = lastSpinCount + AdditionalSpins; + + do { + if (spinCount++ > maximumSpinCount) { + // puts("spinning useless, sleeping"); + bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; + if (!isLocked) { + + // didn't get the lock, wait for it + isLocked = d->wait(); + Q_ASSERT_X(isLocked, "QMutex::lock", + "Internal error, infinite wait has timed out."); + + // don't need to wait for the lock anymore + d->contenders.deref(); + } + // decrease the lastSpinCount since we didn't actually get the lock by spinning + spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; + break; + } + } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1)); + + // adjust the last spin lock count + lastSpinCount = d->lastSpinCount; + d->lastSpinCount = spinCount >= 0 + ? qMax(lastSpinCount, spinCount) + : lastSpinCount + spinCount; +} + +/*! + \internal +*/ +void QMutex::unlockInternal() +{ + static_cast<QMutexPrivate *>(d)->wakeUp(); +} + +/*! + \fn QMutex::lockInline() + \internal + inline version of QMutex::lock() +*/ + +/*! + \fn QMutex::unlockInline() + \internal + inline version of QMutex::unlock() +*/ + +/*! + \fn QMutex::tryLockInline() + \internal + inline version of QMutex::tryLock() +*/ + + QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 509f300..710b794 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -43,6 +43,7 @@ #define QMUTEX_H #include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> #include <new> QT_BEGIN_HEADER @@ -53,7 +54,8 @@ QT_MODULE(Core) #ifndef QT_NO_THREAD -class QMutexPrivate; +class QAtomicInt; +class QMutexData; class Q_CORE_EXPORT QMutex { @@ -66,10 +68,13 @@ public: explicit QMutex(RecursionMode mode = NonRecursive); ~QMutex(); - void lock(); - bool tryLock(); + void lock(); //### Qt5: make inline; + inline void lockInline(); + bool tryLock(); //### Qt5: make inline; bool tryLock(int timeout); - void unlock(); + inline bool tryLockInline(); + void unlock(); //### Qt5: make inline; + inline void unlockInline(); #if defined(QT3_SUPPORT) inline QT3_SUPPORT bool locked() @@ -86,9 +91,11 @@ public: #endif private: + void lockInternal(); + void unlockInternal(); Q_DISABLE_COPY(QMutex) - QMutexPrivate *d; + QMutexData *d; }; class Q_CORE_EXPORT QMutexLocker @@ -99,7 +106,7 @@ public: Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); if (m) { - m->lock(); + m->lockInline(); val = reinterpret_cast<quintptr>(m) | quintptr(1u); } else { val = 0; @@ -111,7 +118,7 @@ public: { if ((val & quintptr(1u)) == quintptr(1u)) { val &= ~quintptr(1u); - mutex()->unlock(); + mutex()->unlockInline(); } } @@ -119,7 +126,7 @@ public: { if (val) { if ((val & quintptr(1u)) == quintptr(0u)) { - mutex()->lock(); + mutex()->lockInline(); val |= quintptr(1u); } } @@ -145,6 +152,46 @@ private: quintptr val; }; +class QMutexData +{ + public: + QAtomicInt contenders; + const uint recursive : 1; + uint reserved : 31; + protected: + QMutexData(QMutex::RecursionMode mode); + ~QMutexData(); +}; + +inline void QMutex::unlockInline() +{ + if (d->recursive) { + unlock(); + } else if (!d->contenders.testAndSetRelease(1, 0)) { + unlockInternal(); + } +} + +inline bool QMutex::tryLockInline() +{ + if (d->recursive) { + return tryLock(); + } else { + return d->contenders.testAndSetAcquire(0, 1); + } +} + +inline void QMutex::lockInline() +{ + if (d->recursive) { + lock(); + } else if(!tryLockInline()) { + lockInternal(); + } +} + + + #else // QT_NO_THREAD @@ -157,9 +204,11 @@ public: inline ~QMutex() {} static inline void lock() {} - static inline bool tryLock() { return true; } - static inline bool tryLock(int timeout) { Q_UNUSED(timeout); return true; } - static void unlock() {} + static inline void lockInline() {} + static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } + static inline bool tryLockInline() { return true; } + static inline void unlock() {} + static inline void unlockInline() {} #if defined(QT3_SUPPORT) static inline QT3_SUPPORT bool locked() { return false; } diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index dce162a..6126423 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -56,10 +56,11 @@ #include <QtCore/qglobal.h> #include <QtCore/qnamespace.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -class QMutexPrivate { +class QMutexPrivate : public QMutexData { public: QMutexPrivate(QMutex::RecursionMode mode); ~QMutexPrivate(); @@ -68,8 +69,6 @@ public: bool wait(int timeout = -1); void wakeUp(); - const bool recursive; - QAtomicInt contenders; volatile int lastSpinCount; Qt::HANDLE owner; uint count; @@ -83,6 +82,12 @@ public: #endif }; +inline QMutexData::QMutexData(QMutex::RecursionMode mode) + : recursive(mode == QMutex::Recursive) +{} + +inline QMutexData::~QMutexData() {} + QT_END_NAMESPACE #endif // QMUTEX_P_H diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index a58368c..7e7ef22 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -63,7 +63,7 @@ static void report_error(int code, const char *where, const char *what) QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0), wakeup(false) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0), wakeup(false) { report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init"); report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init"); diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 9d58953..a810000 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0) { event = CreateEvent(0, FALSE, FALSE, 0); if (!event) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 702125c..375ded1 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE -class QMutex; +#include <QtCore/qmutex.h> /* Locks 2 mutexes in a defined order, avoiding a recursive lock if @@ -79,8 +79,8 @@ public: void relock() { if (!locked) { - if (mtx1) mtx1->lock(); - if (mtx2) mtx2->lock(); + if (mtx1) mtx1->lockInline(); + if (mtx2) mtx2->lockInline(); locked = true; } } @@ -88,8 +88,8 @@ public: void unlock() { if (locked) { - if (mtx1) mtx1->unlock(); - if (mtx2) mtx2->unlock(); + if (mtx1) mtx1->unlockInline(); + if (mtx2) mtx2->unlockInline(); locked = false; } } @@ -100,10 +100,10 @@ public: if (mtx1 == mtx2) return false; if (mtx1 < mtx2) { - mtx2->lock(); + mtx2->lockInline(); return true; } - if (!mtx2->tryLock()) { + if (!mtx2->tryLockInline()) { mtx1->unlock(); mtx2->lock(); mtx1->lock(); diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 3a786ba..6264674 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -91,8 +91,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T **t) { (void) d.set(*t); } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // value-based specialization template <typename T> inline @@ -116,8 +114,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T *t) { (void) d.set(new T(*t)); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // MOC_SKIP_END #endif diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 8d38e4c..3062c4a 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -542,12 +542,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) forever { ulong alloc = len; - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + alloc)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); int res = ::uncompress((uchar*)d->array, &len, (uchar*)data+4, nbytes-4); @@ -555,12 +557,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) switch (res) { case Z_OK: if (len != alloc) { - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + len)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); } d->ref = 1; d->alloc = d->size = len; diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 44477d7..debab7d 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -61,7 +61,7 @@ class QCache }; Node *f, *l; QHash<Key, Node> hash; - void *unused; + void *unused; // ### Qt5: remove int mx, total; inline void unlink(Node &n) { diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index cb5e701..4adddf9 100644 --- a/src/corelib/tools/qelapsedtimer.cpp +++ b/src/corelib/tools/qelapsedtimer.cpp @@ -136,10 +136,11 @@ QT_BEGIN_NAMESPACE implementations, to guarantee that the same reference clock is being used. - \value SystemTime The human-readable system time. This clock is not monotonic. - \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. - \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. - \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value SystemTime The human-readable system time. This clock is not monotonic. + \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. + \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. + \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow. \section2 SystemTime @@ -163,7 +164,9 @@ QT_BEGIN_NAMESPACE The tick counter clock type is based on the system's or the processor's tick counter, multiplied by the duration of a tick. This clock type is - used on Windows and Symbian platforms. + used on Windows and Symbian platforms. If the high-precision performance + counter is available on Windows, the \tt{PerformanceCounter} clock type + is used instead. The TickCounter clock type is the only clock type that may overflow. Windows Vista and Windows Server 2008 support the extended 64-bit tick @@ -191,6 +194,16 @@ QT_BEGIN_NAMESPACE This clock is monotonic and does not overflow. + \section2 PerformanceCounter + + This clock uses the Windows functions \tt{QueryPerformanceCounter} and + \tt{QueryPerformanceFrequency} to access the system's high-precision + performance counter. Since this counter may not be available on all + systems, QElapsedTimer will fall back to the \tt{TickCounter} clock + automatically, if this clock cannot be used. + + This clock is monotonic and does not overflow. + \sa clockType(), isMonotonic() */ diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h index 0d6f0be..b996f6a 100644 --- a/src/corelib/tools/qelapsedtimer.h +++ b/src/corelib/tools/qelapsedtimer.h @@ -57,7 +57,8 @@ public: SystemTime, MonotonicClock, TickCounter, - MachAbsoluteTime + MachAbsoluteTime, + PerformanceCounter }; static ClockType clockType(); static bool isMonotonic(); diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp index 135196a..c77acaa 100644 --- a/src/corelib/tools/qelapsedtimer_win.cpp +++ b/src/corelib/tools/qelapsedtimer_win.cpp @@ -42,6 +42,9 @@ #include "qelapsedtimer.h" #include <windows.h> +// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable +static quint64 counterFrequency = 0; + typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void); static PtrGetTickCount64 ptrGetTickCount64 = 0; @@ -65,12 +68,44 @@ static void resolveLibs() ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, "GetTickCount64"); #endif + // Retrieve the number of high-resolution performance counter ticks per second + LARGE_INTEGER frequency; + if (!QueryPerformanceFrequency(&frequency)) { + counterFrequency = 0; + } else { + counterFrequency = frequency.QuadPart; + } + done = true; } +static inline qint64 ticksToMilliseconds(qint64 ticks) +{ + if (counterFrequency > 0) { + // QueryPerformanceCounter uses an arbitrary frequency + return ticks * 1000 / counterFrequency; + } else { + // GetTickCount(64) return milliseconds + return ticks; + } +} + static quint64 getTickCount() { resolveLibs(); + + // This avoids a division by zero and disables the high performance counter if it's not available + if (counterFrequency > 0) { + LARGE_INTEGER counter; + + if (QueryPerformanceCounter(&counter)) { + return counter.QuadPart; + } else { + qWarning("QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded."); + return 0; + } + } + if (ptrGetTickCount64) return ptrGetTickCount64(); @@ -85,7 +120,12 @@ static quint64 getTickCount() QElapsedTimer::ClockType QElapsedTimer::clockType() { - return TickCounter; + resolveLibs(); + + if (counterFrequency > 0) + return PerformanceCounter; + else + return TickCounter; } bool QElapsedTimer::isMonotonic() @@ -104,22 +144,24 @@ qint64 QElapsedTimer::restart() qint64 oldt1 = t1; t1 = getTickCount(); t2 = 0; - return t1 - oldt1; + return ticksToMilliseconds(t1 - oldt1); } qint64 QElapsedTimer::elapsed() const { - return getTickCount() - t1; + qint64 elapsed = getTickCount() - t1; + return ticksToMilliseconds(elapsed); } qint64 QElapsedTimer::msecsSinceReference() const { - return t1; + return ticksToMilliseconds(t1); } qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const { - return other.t1 - t1; + qint64 difference = other.t1 - t1; + return ticksToMilliseconds(difference); } qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index c7e4bc1..14ed514 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -225,7 +225,7 @@ struct QHashNode inline bool same_key(uint h0, const Key &key0) { return h0 == h && key0 == key; } }; -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + #define Q_HASH_DECLARE_INT_NODES(key_type) \ template <class T> \ struct QHashDummyNode<key_type, T> { \ @@ -253,7 +253,6 @@ Q_HASH_DECLARE_INT_NODES(ushort); Q_HASH_DECLARE_INT_NODES(int); Q_HASH_DECLARE_INT_NODES(uint); #undef Q_HASH_DECLARE_INT_NODES -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> class QHash @@ -513,8 +512,6 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node) { #ifdef Q_CC_BOR concrete(node)->~QHashNode<Key, T>(); -#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) - concrete(node)->~QHashNode(); #else concrete(node)->~Node(); #endif diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index d843cbe..1282bca 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -713,7 +713,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { - if (d && !d->ref.deref()) + if (!d->ref.deref()) free(d); } @@ -741,8 +741,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data) { node_destruct(reinterpret_cast<Node *>(data->array + data->begin), reinterpret_cast<Node *>(data->array + data->end)); - if (data->ref == 0) - qFree(data); + qFree(data); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 1c2aad3..08f5a35 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -107,7 +107,6 @@ template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key return key1 < key2; } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2) { Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *)); @@ -119,7 +118,6 @@ template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *)); return quintptr(key1) < quintptr(key2); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> struct QMapNode { @@ -640,13 +638,13 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x) while (next != x) { cur = next; next = cur->forward[0]; -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(disable:4189) #endif Node *concreteNode = concrete(reinterpret_cast<QMapData::Node *>(cur)); concreteNode->key.~Key(); concreteNode->value.~T(); -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(default:4189) #endif } diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index bc76a3b..40d3851 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -54,7 +54,7 @@ struct QScopedPointerDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -69,7 +69,7 @@ struct QScopedPointerArrayDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -186,11 +186,18 @@ template <class T, class Cleanup> Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) { p1.swap(p2); } +namespace QtPrivate { + template <typename X, typename Y> struct QScopedArrayEnsureSameType; + template <typename X> struct QScopedArrayEnsureSameType<X,X> { typedef X* Type; }; + template <typename X> struct QScopedArrayEnsureSameType<const X, X> { typedef X* Type; }; +} + template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { public: - explicit inline QScopedArrayPointer(T *p = 0) + template <typename D> + explicit inline QScopedArrayPointer(D *p = 0, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = 0) : QScopedPointer<T, Cleanup>(p) { } @@ -206,6 +213,17 @@ public: } private: + explicit inline QScopedArrayPointer(void *) { + // Enforce the same type. + + // If you get a compile error here, make sure you declare + // QScopedArrayPointer with the same template type as you pass to the + // constructor. See also the QScopedPointer documentation. + + // Storing a scalar array as a pointer to a different type is not + // allowed and results in undefined behavior. + } + Q_DISABLE_COPY(QScopedArrayPointer) }; diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 6483c90..1ae2fa9 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -163,14 +163,12 @@ public: explicit QExplicitlySharedDataPointer(T *data); inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<class X> inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data())) { if(d) d->ref.ref(); } -#endif inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { if (o.d != d) { diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 5fac960..8f9559a 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1275,8 +1275,6 @@ QT_END_NAMESPACE -#if !defined(QT_NO_MEMBER_TEMPLATES) - //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT # ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT # if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) @@ -1501,5 +1499,3 @@ void QtSharedPointer::internalSafetyCheckCleanCheck() } QT_END_NAMESPACE - -#endif diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index c51ade6..e0f4dca 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -47,10 +47,7 @@ #include <QtCore/qshareddata.h> #ifndef Q_QDOC -# if !defined(QT_NO_MEMBER_TEMPLATES) -// QSharedPointer requires member template support # include <QtCore/qsharedpointer_impl.h> -# endif #else QT_BEGIN_HEADER diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 4cce339..bb06f3a 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -109,7 +109,6 @@ namespace QtSharedPointer { template <class T> inline void normalDeleter(T *t) { delete t; } // this uses partial template specialization - // the only compilers that didn't support this were MSVC 6.0 and 2002 template <class T> struct RemovePointer; template <class T> struct RemovePointer<T *> { typedef T Type; }; template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; @@ -323,7 +322,6 @@ namespace QtSharedPointer { protected: typedef ExternalRefCountData Data; - inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void deref() { deref(d, this->value); } static inline void deref(Data *d, T *value) @@ -388,7 +386,13 @@ namespace QtSharedPointer { template <class X> inline void internalCopy(const ExternalRefCount<X> &other) { - internalSet(other.d, other.data()); + Data *o = other.d; + T *actual = other.value; + if (o) + other.ref(); + qSwap(d, o); + qSwap(this->value, actual); + deref(o, actual); } inline void internalSwap(ExternalRefCount &other) @@ -404,6 +408,7 @@ namespace QtSharedPointer { template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer); template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); #endif + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void internalSet(Data *o, T *actual) { @@ -844,9 +849,13 @@ qobject_cast(const QWeakPointer<T> &src) { return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); } - #endif + +template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE); +template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE); + + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 2fd9a0b..de45a63 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -111,7 +111,23 @@ int qFindString(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); - +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar &needle, Qt::CaseSensitivity cs); +static inline int qt_find_latin1_string(const QChar *hay, int size, const QLatin1String &needle, + int from, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); // Unicode case-insensitive comparison static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) @@ -320,11 +336,7 @@ inline char qToLower(char ch) return ch; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -const QString::Null QString::null; -#else const QString::Null QString::null = { }; -#endif /*! \macro QT_NO_CAST_FROM_ASCII @@ -915,6 +927,24 @@ QString QString::fromWCharArray(const wchar_t *string, int size) \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit() */ +template<typename T> int toUcs4_helper(const unsigned short *uc, int length, T *out) +{ + int i = 0; + for (; i < length; ++i) { + uint u = uc[i]; + if (QChar::isHighSurrogate(u) && i < length-1) { + ushort low = uc[i+1]; + if (QChar::isLowSurrogate(low)) { + ++i; + u = QChar::surrogateToUcs4(u, low); + } + } + *out = T(u); + ++out; + } + return i; +} + /*! \since 4.2 @@ -939,21 +969,7 @@ int QString::toWCharArray(wchar_t *array) const memcpy(array, utf16(), sizeof(wchar_t)*length()); return length(); } else { - wchar_t *a = array; - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar::isHighSurrogate(u) && i + 1 < length()) { - ushort low = uc[i+1]; - if (QChar::isLowSurrogate(low)) { - u = QChar::surrogateToUcs4(u, low); - ++i; - } - } - *a = wchar_t(u); - ++a; - } - return a - array; + return toUcs4_helper<wchar_t>(utf16(), length(), array); } } @@ -1286,7 +1302,9 @@ void QString::realloc(int alloc) asciiCache->remove(d); } #endif - d = static_cast<Data *>(q_check_ptr(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)))); + Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Q_CHECK_PTR(p); + d = p; d->alloc = alloc; d->data = d->array; } @@ -2450,14 +2468,10 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const \sa lastIndexOf(), contains(), count() */ + int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const { - int len = qstrlen(str.latin1()); - QVarLengthArray<ushort> s(len); - for (int i = 0; i < len; ++i) - s[i] = str.latin1()[i]; - - return qFindString(unicode(), length(), from, (const QChar *)s.data(), len, cs); + return qt_find_latin1_string(unicode(), size(), str, from, cs); } int qFindString( @@ -2547,6 +2561,23 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const return findChar(unicode(), length(), ch, from, cs); } +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string, searching forward from index + position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) { /* @@ -2626,12 +2657,13 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); } /*! \since 4.5 + \overload lastIndexOf() + Returns the index position of the last occurrence of the string \a str in this string, searching backward from index position \a from. If \a from is -1 (default), the search starts at the last @@ -2679,26 +2711,43 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity */ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - if (from < 0) - from += d->size; - if (from < 0 || from >= d->size) - return -1; - if (from >= 0) { - const ushort *n = d->data + from; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - for (; n >= b; --n) - if (*n == c) - return n - b; - } else { - c = foldCase(c); - for (; n >= b; --n) - if (foldCase(*n) == c) - return n - b; - } + return qt_last_index_of(unicode(), size(), ch, from, cs); } + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string, searching backward from index + position \a from. If \a from is -1 (default), the search starts at + the last character; if \a from is -2, at the next to last character + and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa indexOf(), contains(), count() +*/ +int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = d->size; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); } #ifndef QT_NO_REGEXP @@ -2873,19 +2922,10 @@ QString& QString::replace(const QRegExp &rx, const QString &after) \sa contains(), indexOf() */ + int QString::count(const QString &str, Qt::CaseSensitivity cs) const { - int num = 0; - int i = -1; - if (d->size > 500 && str.d->size > 5) { - QStringMatcher matcher(str, cs); - while ((i = matcher.indexIn(*this, i + 1)) != -1) - ++num; - } else { - while ((i = indexOf(str, i + 1, cs)) != -1) - ++num; - } - return num; + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } /*! @@ -2893,25 +2933,29 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const Returns the number of occurrences of character \a ch in the string. */ + int QString::count(QChar ch, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - int num = 0; - const ushort *i = d->data + d->size; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - while (i != b) - if (*--i == c) - ++num; - } else { - c = foldCase(c); - while (i != b) - if (foldCase(*(--i)) == c) - ++num; + return qt_string_count(unicode(), size(), ch, cs); } - return num; + +/*! + \since 4.8 + \overload count() + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() +*/ +int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } + /*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Returns true if this string contains an occurrence of the string @@ -2934,6 +2978,18 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const character \a ch; otherwise returns false. */ +/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.8 + + Returns true if this string contains an occurrence of the string + reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + /*! \fn bool QString::contains(const QRegExp &rx) const \overload contains() @@ -3335,22 +3391,8 @@ QString QString::mid(int position, int n) const */ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - if (s.d->size > d->size) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.d->size; ++i) - if (foldCase(d->data[i], last) != foldCase(s.d->data[i], olast)) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } /*! @@ -3358,24 +3400,7 @@ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const */ bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - if (slen > d->size) - return false; - const uchar *latin = (const uchar *)s.latin1(); - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; ++i) - if (d->data[i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; ++i) - if (foldCase(d->data[i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3393,6 +3418,23 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const } /*! + \since 4.8 + \overload + Returns true if the string starts with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa endsWith() +*/ +bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); +} + +/*! Returns true if the string ends with \a s; otherwise returns false. @@ -3405,49 +3447,34 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const */ bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - int pos = d->size - s.d->size; - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data + pos, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.length(); i++) - if (foldCase(d->data[pos+i], last) != foldCase(s.d->data[i], olast)) - return false; + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } - return true; + +/*! + \since 4.8 + \overload endsWith() + Returns true if the string ends with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa startsWith() +*/ +bool QString::endsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } + /*! \overload endsWith() */ bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - int pos = d->size - slen; - const uchar *latin = (const uchar *)s.latin1(); - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; i++) - if (d->data[pos+i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; i++) - if (foldCase(d->data[pos+i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_ends_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3686,20 +3713,8 @@ QVector<uint> QString::toUcs4() const { QVector<uint> v(length()); uint *a = v.data(); - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar(u).isHighSurrogate() && i < length()-1) { - ushort low = uc[i+1]; - if (QChar(low).isLowSurrogate()) { - ++i; - u = QChar::surrogateToUcs4(u, low); - } - } - *a = u; - ++a; - } - v.resize(a - v.data()); + int len = toUcs4_helper<uint>(utf16(), length(), a); + v.resize(len); return v; } @@ -7629,6 +7644,7 @@ QDataStream &operator>>(QDataStream &in, QString &str) Use the startsWith(QString, Qt::CaseSensitive) overload instead. */ + /*! \fn bool QString::endsWith(const QString &s, bool cs) const @@ -8334,4 +8350,717 @@ QStringRef QString::midRef(int position, int n) const return QStringRef(this, position, n); } +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + +/*! + \since 4.8 + \overload indexOf() + + Returns the index position of the first occurrence of the + character \a ch in the string reference, searching forward from + index position \a from. Returns -1 if \a ch could not be found. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return findChar(unicode(), length(), ch, from, cs); +} + +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + return qt_find_latin1_string(unicode(), size(), str, from, cs); +} + +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string reference, searching forward from + index position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size();; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), str.size(), cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the character + \a ch, searching backward from position \a from. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return qt_last_index_of(unicode(), size(), ch, from, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = qstrlen(str.latin1()); + if (sl == 1) + return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + QVarLengthArray<ushort> s(sl); + for (int i = 0; i < sl; ++i) + s[i] = str.latin1()[i]; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, s.data(), sl, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string reference, searching backward from + index position \a from. If \a from is -1 (default), the search + starts at the last character; if \a from is -2, at the next to last + character and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); +} + +/*! + \since 4.8 + Returns the number of (potentially overlapping) occurrences of + the string \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of occurrences of the character \a ch in the + string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), ch, cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns true if the string reference starts with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + + Returns true if the string reference starts with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + return (cs == Qt::CaseSensitive + ? data[0] == ch + : foldCase(data[0]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + Returns true if the string reference ends with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), startsWith() +*/ +bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload endsWith() + + Returns true if the string reference ends with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + const int size = length(); + return (cs == Qt::CaseSensitive + ? data[size - 1] == ch + : foldCase(data[size - 1]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + + +/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \since 4.8 + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \overload contains() + \since 4.8 + + Returns true if this string contains an occurrence of the + character \a ch; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + +*/ + +/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \overload contains() + \since 4.8 + + Returns true if this string reference contains an occurrence of + the string reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const + \since 4,8 + \overload contains() + + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs) +{ + ushort c = needle.unicode(); + if (from < 0) + from += haystackLen; + if (from < 0 || from >= haystackLen) + return -1; + if (from >= 0) { + const ushort *b = reinterpret_cast<const ushort*>(haystack); + const ushort *n = b + from; + if (cs == Qt::CaseSensitive) { + for (; n >= b; --n) + if (*n == c) + return n - b; + } else { + c = foldCase(c); + for (; n >= b; --n) + if (foldCase(*n) == c) + return n - b; + } + } + return -1; + + +} + +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs) +{ + int num = 0; + int i = -1; + if (haystackLen > 500 && needleLen > 5) { + QStringMatcher matcher(needle, needleLen, cs); + while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1) + ++num; + } else { + while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1) + ++num; + } + return num; +} + +static inline int qt_string_count(const QChar *unicode, int size, const QChar &ch, + Qt::CaseSensitivity cs) +{ + ushort c = ch.unicode(); + int num = 0; + const ushort *b = reinterpret_cast<const ushort*>(unicode); + const ushort *i = b + size; + if (cs == Qt::CaseSensitive) { + while (i != b) + if (*--i == c) + ++num; + } else { + c = foldCase(c); + while (i != b) + if (foldCase(*(--i)) == c) + ++num; + } + return num; +} + +static inline int qt_find_latin1_string(const QChar *haystack, int size, + const QLatin1String &needle, + int from, Qt::CaseSensitivity cs) +{ + const char *latin1 = needle.latin1(); + int len = qstrlen(latin1); + QVarLengthArray<ushort> s(len); + for (int i = 0; i < len; ++i) + s[i] = latin1[i]; + + return qFindString(haystack, size, from, + reinterpret_cast<const QChar*>(s.constData()), len, cs); +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + if (needleLen > haystackLen) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; ++i) + if (foldCase(h[i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + if (slen > haystackLen) + return false; + const ushort *data = reinterpret_cast<const ushort*>(haystack); + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; ++i) + if (data[i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; ++i) + if (foldCase(data[i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + const int pos = haystackLen - needleLen; + if (pos < 0) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h + pos, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; i++) + if (foldCase(h[pos+i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + int pos = haystackLen - slen; + if (pos < 0) + return false; + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + const ushort *data = reinterpret_cast<const ushort*>(haystack); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; i++) + if (data[pos+i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; i++) + if (foldCase(data[pos+i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +/*! + \since 4.8 + + Returns a Latin-1 representation of the string as a QByteArray. + + The returned byte array is undefined if the string contains non-Latin1 + characters. Those characters may be suppressed or replaced with a + question mark. + + \sa toAscii(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toLatin1() const +{ + return toLatin1_helper(unicode(), length()); +} + +/*! + \since 4.8 + + Returns an 8-bit representation of the string as a QByteArray. + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert Unicode to 8-bit char; otherwise this + function does the same as toLatin1(). + + Note that, despite the name, this function does not necessarily return an US-ASCII + (ANSI X3.4-1986) string and its result may not be US-ASCII compatible. + + \sa toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toAscii() const +{ +#ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) + return QString::codecForCStrings->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns the local 8-bit representation of the string as a + QByteArray. The returned byte array is undefined if the string + contains characters not supported by the local 8-bit encoding. + + QTextCodec::codecForLocale() is used to perform the conversion from + Unicode. If the locale encoding could not be determined, this function + does the same as toLatin1(). + + If this string contains any characters that cannot be encoded in the + locale, the returned byte array is undefined. Those characters may be + suppressed or replaced by another. + + \sa toAscii(), toLatin1(), toUtf8(), QTextCodec +*/ +QByteArray QStringRef::toLocal8Bit() const +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns a UTF-8 representation of the string as a QByteArray. + + UTF-8 is a Unicode codec and can represent all characters in a Unicode + string like QString. + + However, in the Unicode range, there are certain codepoints that are not + considered characters. The Unicode standard reserves the last two + codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, + U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF, + inclusive, as non-characters. If any of those appear in the string, they + may be discarded and will not appear in the UTF-8 representation, or they + may be replaced by one or more replacement characters. + + \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toUtf8() const +{ + if (isNull()) + return QByteArray(); + + return QUtf8::convertFromUnicode(constData(), length(), 0); +} + +/*! + \since 4.8 + + Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>. + + UCS-4 is a Unicode codec and is lossless. All characters from this string + can be encoded in UCS-4. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() +*/ +QVector<uint> QStringRef::toUcs4() const +{ + QVector<uint> v(length()); + uint *a = v.data(); + int len = toUcs4_helper<uint>(reinterpret_cast<const unsigned short *>(unicode()), length(), a); + v.resize(len); + return v; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index e52f59f..2252353 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -51,14 +51,7 @@ #endif #ifndef QT_NO_STL -# if defined (Q_CC_MSVC_NET) && _MSC_VER < 1310 // Avoids nasty warning for xlocale, line 450 -# pragma warning (push) -# pragma warning (disable : 4189) -# include <string> -# pragma warning (pop) -# else -# include <string> -# endif +# include <string> # ifndef QT_NO_STL_WCHAR // workaround for some headers not typedef'ing std::wstring @@ -198,14 +191,18 @@ public: int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QLatin1String &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QLatin1String &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; #ifndef QT_NO_REGEXP int indexOf(const QRegExp &, int from = 0) const; @@ -241,9 +238,11 @@ public: QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT; bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -901,6 +900,8 @@ inline QString::const_iterator QString::constEnd() const { return reinterpret_cast<const QChar*>(d->data + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return QBool(indexOf(c, 0, cs) != -1); } @@ -1122,6 +1123,34 @@ public: m_size = other.m_size; return *this; } + int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QStringRef &operator=(const QString *string); inline const QChar *unicode() const { @@ -1132,6 +1161,12 @@ public: inline const QChar *data() const { return unicode(); } inline const QChar *constData() const { return unicode(); } + QByteArray toAscii() const Q_REQUIRED_RESULT; + QByteArray toLatin1() const Q_REQUIRED_RESULT; + QByteArray toUtf8() const Q_REQUIRED_RESULT; + QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; + QVector<uint> toUcs4() const Q_REQUIRED_RESULT; + inline void clear() { m_string = 0; m_position = m_size = 0; } QString toString() const; inline bool isEmpty() const { return m_size == 0; } @@ -1240,6 +1275,16 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2) { return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +inline QBool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(c, 0, cs) != -1); } +inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } + + QT_END_NAMESPACE diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index b762b8a..2f0ad42 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -790,11 +790,8 @@ QT_END_INCLUDE_NAMESPACE #else #define Q_TEMPLATE_EXTERN extern #endif -# pragma warning(push) /* MSVC 6.0 doesn't care about the disabling in qglobal.h (why?), so do it here */ -# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>; Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>; -# pragma warning(pop) #endif QT_END_NAMESPACE diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 4e9c1ad..9ff0ff1 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -208,7 +208,7 @@ bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q QLatin1String(DBUS_INTERFACE_PROPERTIES), QLatin1String("Set")); QDBusMessagePrivate::setParametersValidated(msg, true); - msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); + msg << interface << QString::fromUtf8(mp.name()) << QVariant::fromValue(QDBusVariant(value)); QDBusMessage reply = connection.call(msg, QDBus::Block); if (reply.type() != QDBusMessage::ReplyMessage) { diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index 6e19218..0df4c6b 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -188,11 +188,11 @@ QVariant QDBusDemarshaller::toVariantInternal() { switch (q_dbus_message_iter_get_arg_type(&iterator)) { case DBUS_TYPE_BYTE: - return qVariantFromValue(toByte()); + return QVariant::fromValue(toByte()); case DBUS_TYPE_INT16: - return qVariantFromValue(toShort()); + return QVariant::fromValue(toShort()); case DBUS_TYPE_UINT16: - return qVariantFromValue(toUShort()); + return QVariant::fromValue(toUShort()); case DBUS_TYPE_INT32: return toInt(); case DBUS_TYPE_UINT32: @@ -208,11 +208,11 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toString(); case DBUS_TYPE_OBJECT_PATH: - return qVariantFromValue(toObjectPath()); + return QVariant::fromValue(toObjectPath()); case DBUS_TYPE_SIGNATURE: - return qVariantFromValue(toSignature()); + return QVariant::fromValue(toSignature()); case DBUS_TYPE_VARIANT: - return qVariantFromValue(toVariant()); + return QVariant::fromValue(toVariant()); case DBUS_TYPE_ARRAY: switch (q_dbus_message_iter_get_element_type(&iterator)) { @@ -222,14 +222,14 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toStringList(); case DBUS_TYPE_DICT_ENTRY: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); } case DBUS_TYPE_STRUCT: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 7951177..b479b32 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -806,14 +806,14 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu slotData.slotIdx = -1; slotData.metaTypes.clear(); slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); return false; } } // save to the cache slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); // found the slot to be called deliverCall(object, flags, msg, slotData.metaTypes, slotData.slotIdx); diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 78abf94..b6cf1fd 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -264,7 +264,7 @@ QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node return propertyNotFoundError(msg, interface_name, property_name); } - return msg.createReply(qVariantFromValue(QDBusVariant(value))); + return msg.createReply(QVariant::fromValue(QDBusVariant(value))); } enum PropertyWriteResult { @@ -334,7 +334,7 @@ static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant // we have to demarshall before writing void *null = 0; QVariant other(id, null); - if (!QDBusMetaType::demarshall(qVariantValue<QDBusArgument>(value), id, other.data())) { + if (!QDBusMetaType::demarshall(qvariant_cast<QDBusArgument>(value), id, other.data())) { qWarning("QDBusConnection: type `%s' (%d) is not registered with QtDBus. " "Use qDBusRegisterMetaType to register it", mp.typeName(), id); @@ -495,7 +495,7 @@ QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &n return interfaceNotFoundError(msg, interface_name); } - return msg.createReply(qVariantFromValue(result)); + return msg.createReply(QVariant::fromValue(result)); } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 1ffe441..bf07080 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -194,7 +194,7 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb { QDeclarativeDebugObjectReference obj; obj.m_debugId = prop.m_value.toInt(); - prop.m_value = qVariantFromValue(obj); + prop.m_value = QVariant::fromValue(obj); break; } case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown: diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index a6e8c85..1e862cc 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1028,10 +1028,50 @@ void QDeclarativeFlickablePrivate::data_append(QDeclarativeListProperty<QObject> o->setParent(prop->object); } +int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *property) +{ + QDeclarativeItem *contentItem= static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + return contentItem->childItems().count() + contentItem->children().count(); +} + +QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *property, int index) +{ + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + + int childItemCount = contentItem->childItems().count(); + + if (index < 0) + return 0; + + if (index < childItemCount) { + return contentItem->childItems().at(index)->toGraphicsObject(); + } else { + return contentItem->children().at(index - childItemCount); + } + + return 0; +} + +void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *property) +{ + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + + const QList<QGraphicsItem*> graphicsItems = contentItem->childItems(); + for (int i = 0; i < graphicsItems.count(); i++) + contentItem->scene()->removeItem(graphicsItems[i]); + + const QList<QObject*> objects = contentItem->children(); + for (int i = 0; i < objects.count(); i++) + objects[i]->setParent(0); +} + QDeclarativeListProperty<QObject> QDeclarativeFlickable::flickableData() { Q_D(QDeclarativeFlickable); - return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append); + return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append, + QDeclarativeFlickablePrivate::data_count, + QDeclarativeFlickablePrivate::data_at, + QDeclarativeFlickablePrivate::data_clear); } QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren() diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index b919e1b..1bde021 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -171,6 +171,9 @@ public: // flickableData property static void data_append(QDeclarativeListProperty<QObject> *, QObject *); + static int data_count(QDeclarativeListProperty<QObject> *); + static QObject * data_at(QDeclarativeListProperty<QObject> *, int); + static void data_clear(QDeclarativeListProperty<QObject> *); }; class QDeclarativeFlickableVisibleArea : public QObject diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.h b/src/declarative/qml/parser/qdeclarativejsengine_p.h index 1389244..d0b744d 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.h +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.h @@ -88,12 +88,6 @@ uint qHash(const QDeclarativeJS::NameId &id); } // end of namespace QDeclarativeJS -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -//this ensures that code outside QDeclarativeJS can use the hash function -//it also a workaround for some compilers -inline uint qHash(const QDeclarativeJS::NameId &nameId) { return QDeclarativeJS::qHash(nameId); } -#endif - namespace QDeclarativeJS { class Lexer; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index c5a5c18..4d244c5 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1291,7 +1291,7 @@ QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEn qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); qsreal z = ctxt->argument(2).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QVector3D(x, y, z))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z))); } /*! @@ -1311,14 +1311,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1339,14 +1339,14 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1430,14 +1430,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } #endif // QT_NO_DATESTRING @@ -1466,7 +1466,7 @@ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a))); } /*! @@ -1494,7 +1494,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a))); } /*! @@ -1517,7 +1517,7 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine if (w < 0 || h < 0) return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QRectF(x, y, w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } /*! @@ -1530,7 +1530,7 @@ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngin return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments")); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QPointF(x, y))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y))); } /*! @@ -1543,7 +1543,7 @@ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments")); qsreal w = ctxt->argument(0).toNumber(); qsreal h = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QSizeF(w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h))); } /*! @@ -1579,7 +1579,7 @@ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEng if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.lighter(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1616,7 +1616,7 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.darker(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1851,7 +1851,7 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine a + inv_a * color.alphaF()); } - return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); + return engine->toScriptValue(QVariant::fromValue(finalColor)); } QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) @@ -1881,7 +1881,7 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v if (objOk) { return objectClass->newQObject(obj); } else { - return qScriptValueFromValue(&scriptEngine, val); + return scriptEngine.toScriptValue(val); } } diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 45f277e..42b596a 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -237,7 +237,7 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn if (!qmlengine->sqlQueryClass) qmlengine->sqlQueryClass = new QDeclarativeSqlQueryScriptClass(engine); QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass); - rows.setData(engine->newVariant(qVariantFromValue(query))); + rows.setData(engine->newVariant(QVariant::fromValue(query))); rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration); result.setProperty(QLatin1String("rows"),rows); result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected()); @@ -275,7 +275,7 @@ static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScri QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); QString foundvers = context->thisObject().property(QLatin1String("version")).toString(); if (from_version!=foundvers) { @@ -319,7 +319,7 @@ static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, Q QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); db.transaction(); callback.call(QScriptValue(), QScriptValueList() << tx); @@ -403,7 +403,7 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly); instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3)); - QScriptValue result = engine->newVariant(instance,qVariantFromValue(database)); + QScriptValue result = engine->newVariant(instance,QVariant::fromValue(database)); if (created && dbcreationCallback.isFunction()) { dbcreationCallback.call(QScriptValue(), QScriptValueList() << result); diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 7534a2c..8ec68ff 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -92,7 +92,7 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) QSizeF sz = sizeFFromString(s, &ok); if (ok) return QVariant(sz); QVector3D v = vector3DFromString(s, &ok); - if (ok) return qVariantFromValue(v); + if (ok) return QVariant::fromValue(v); return QVariant(s); } diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 789116e..509ca6b 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -331,7 +331,7 @@ QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScri QDeclarativeListModelWorkerAgent *agent = lm->agent(); if (agent) { QDeclarativeListModelWorkerAgent::VariantRef v(agent); - return qVariantFromValue(v); + return QVariant::fromValue(v); } else { return QVariant(); } diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index d832638..301ea1d 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -58,6 +58,8 @@ #include <QtCore/qstack.h> #include <QtCore/qdebug.h> +#include <QtCore/QStringBuilder> + #ifndef QT_NO_XMLSTREAMREADER // From DOM-Level-3-Core spec @@ -510,7 +512,7 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data) node.d = data; if (data) A(data); - return engine->newVariant(instance, qVariantFromValue(node)); + return engine->newVariant(instance, QVariant::fromValue(node)); } QScriptValue Element::prototype(QScriptEngine *engine) @@ -710,7 +712,7 @@ QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data) instance.setPrototype(Document::prototype(engine)); Node documentNode; documentNode.d = document; - return engine->newVariant(instance, qVariantFromValue(documentNode)); + return engine->newVariant(instance, QVariant::fromValue(documentNode)); } Node::Node() @@ -761,7 +763,7 @@ QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<N map.list = list; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(map))); + instance.setData(engine->newVariant(QVariant::fromValue(map))); if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass) QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine); @@ -818,7 +820,7 @@ QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data) list.d = data; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(list))); + instance.setData(engine->newVariant(QVariant::fromValue(list))); if (!QDeclarativeScriptEngine::get(engine)->nodeListClass) QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine); @@ -1090,10 +1092,9 @@ QString QDeclarativeXMLHttpRequest::headers() foreach (const HeaderPair &header, m_headersList) { if (ret.length()) - ret.append(QString::fromUtf8("\r\n")); - ret.append(QString::fromUtf8(header.first)); - ret.append(QString::fromUtf8(": ")); - ret.append(QString::fromUtf8(header.second)); + ret.append(QLatin1String("\r\n")); + ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ") + % QString::fromUtf8(header.second); } return ret; } @@ -1105,9 +1106,9 @@ void QDeclarativeXMLHttpRequest::fillHeadersList() m_headersList.clear(); foreach (const QByteArray &header, headerList) { HeaderPair pair (header.toLower(), m_network->rawHeader(header)); - if (pair.first == "set-cookie" || - pair.first == "set-cookie2") - continue; + if (pair.first == "set-cookie" || + pair.first == "set-cookie2") + continue; m_headersList << pair; } diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index d15d1f6..8cb17e4 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -63,7 +63,7 @@ QT_MODULE(Declarative) class QDeclarativeAbstractAnimationPrivate; class QDeclarativeAnimationGroup; -class Q_AUTOTEST_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus +class Q_DECLARATIVE_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAbstractAnimation) @@ -165,7 +165,7 @@ protected: }; class QDeclarativeScriptActionPrivate; -class QDeclarativeScriptAction : public QDeclarativeAbstractAnimation +class Q_DECLARATIVE_EXPORT QDeclarativeScriptAction : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeScriptAction) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 0162beb..d84de26 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -708,7 +708,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & { ModelNode *n = nodes.top(); ModelNode *n2 = new ModelNode; - n->values << qVariantFromValue(n2); + n->values << QVariant::fromValue(n2); nodes.push(n2); if (processingSet) n->isArray = true; @@ -865,7 +865,7 @@ QScriptValue FlatListModel::get(int index) const QHash<int, QVariant> row = m_values.at(index); for (QHash<int, QVariant>::ConstIterator iter = row.begin(); iter != row.end(); ++iter) - rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value())); + rv.setProperty(m_roles.value(iter.key()), scriptEngine->toScriptValue(iter.value())); return rv; } @@ -1076,7 +1076,7 @@ bool NestedListModel::insert(int index, const QScriptValue& valuemap) ModelNode *mn = new ModelNode; mn->setObjectValue(valuemap); - _root->values.insert(index,qVariantFromValue(mn)); + _root->values.insert(index,QVariant::fromValue(mn)); return true; } @@ -1109,7 +1109,7 @@ bool NestedListModel::append(const QScriptValue& valuemap) } ModelNode *mn = new ModelNode; mn->setObjectValue(valuemap); - _root->values << qVariantFromValue(mn); + _root->values << QVariant::fromValue(mn); return true; } @@ -1264,7 +1264,7 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { } else { value->values << v.toVariant(); } - values.append(qVariantFromValue(value)); + values.append(QVariant::fromValue(value)); } } diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 7b3d4a8..cef78af 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -811,7 +811,7 @@ QScriptValue QDeclarativeXmlListModel::get(int index) const QScriptValue sv = sengine->newObject(); for (int i=0; i<d->roleObjects.count(); i++) - sv.setProperty(d->roleObjects[i]->name(), qScriptValueFromValue(sengine, d->data.value(i).value(index))); + sv.setProperty(d->roleObjects[i]->name(), sengine->toScriptValue(d->data.value(i).value(index))); return sv; } diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 0921bdb..a6d1dbd 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -409,13 +409,18 @@ static void qAccessibleCleanup() /*! \typedef QAccessible::InterfaceFactory - A function pointer type. Use a function with this prototype to install - interface factories with installFactory(). + This is a typedef for a pointer to a function with the following + signature: - The function receives a QObject pointer. If the QObject - provides a QAccessibleInterface, it sets the second parameter to - point to the corresponding QAccessibleInterface, and returns true; - otherwise returns false. + \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 1 + + The function receives a QString and a QObject pointer, where the + QString is the key identifying the interface. The QObject is used + to pass on to the QAccessibleInterface so that it can hold a reference + to it. + + If the key and the QObject does not have a corresponding + QAccessibleInterface, a null-pointer will be returned. Installed factories are called by queryAccessibilityInterface() until one provides an interface. diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp index 7b2e7ce..3a4809e 100644 --- a/src/gui/accessible/qaccessibleobject.cpp +++ b/src/gui/accessible/qaccessibleobject.cpp @@ -276,7 +276,7 @@ QAccessible::Relation QAccessibleApplication::relationTo(int child, const for (int i = 0; i < tlw.count(); ++i) { QWidget *w = tlw.at(i); - QObjectList cl = qFindChildren<QObject *>(w, QString()); + QObjectList cl = w->findChildren<QObject *>(QString()); if (cl.contains(o)) return Ancestor; } diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp index 7c13367..5b439a9 100644 --- a/src/gui/accessible/qaccessiblewidget.cpp +++ b/src/gui/accessible/qaccessiblewidget.cpp @@ -1015,7 +1015,7 @@ QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVa case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << ForegroundColor << BackgroundColor; - return qVariantFromValue(set); + return QVariant::fromValue(set); } case ForegroundColor: return widget()->palette().color(widget()->foregroundRole()); diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 9e0437c..5a791fc 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -337,7 +337,7 @@ void QDialogPrivate::setDefault(QPushButton *pushButton) { Q_Q(QDialog); bool hasMain = false; - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->window() == q) { @@ -372,7 +372,7 @@ void QDialogPrivate::setMainDefault(QPushButton *pushButton) void QDialogPrivate::hideDefault() { Q_Q(QDialog); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { list.at(i)->setDefault(false); } @@ -675,7 +675,7 @@ void QDialog::keyPressEvent(QKeyEvent *e) switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: { - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->isDefault() && pb->isVisible()) { diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index cb74a3c..a0dca5d 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -2209,9 +2209,9 @@ void QFileDialogPrivate::createWidgets() #ifndef QT_NO_FSCOMPLETER completer = new QFSCompleter(model, q); qFileDialogUi->fileNameEdit->setCompleter(completer); +#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_autoCompleteFileName(QString))); -#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_updateOkButton())); diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 8a6190f..b8aafe3 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1290,6 +1290,10 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/')) fullPath = fullPath.mid(1); #endif +#if defined(Q_OS_WIN) + if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':'))) + fullPath.append(QLatin1Char('/')); +#endif return fullPath; } @@ -1608,6 +1612,14 @@ bool QFileSystemModel::event(QEvent *event) return QAbstractItemModel::event(event); } +bool QFileSystemModel::rmdir(const QModelIndex &aindex) const +{ + QString path = filePath(aindex); + QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func()); + d->fileInfoGatherer.removePath(path); + return QDir().rmdir(path); +} + /*! \internal diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h index d8178c7..741f22b 100644 --- a/src/gui/dialogs/qfilesystemmodel.h +++ b/src/gui/dialogs/qfilesystemmodel.h @@ -139,7 +139,7 @@ public: QDateTime lastModified(const QModelIndex &index) const; QModelIndex mkdir(const QModelIndex &parent, const QString &name); - inline bool rmdir(const QModelIndex &index) const; + bool rmdir(const QModelIndex &index) const; // ### Qt5: should not be const inline QString fileName(const QModelIndex &index) const; inline QIcon fileIcon(const QModelIndex &index) const; QFile::Permissions permissions(const QModelIndex &index) const; @@ -163,8 +163,6 @@ private: friend class QFileDialogPrivate; }; -inline bool QFileSystemModel::rmdir(const QModelIndex &aindex) const -{ QDir dir; return dir.rmdir(filePath(aindex)); } inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const { return aindex.data(Qt::DisplayRole).toString(); } inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index fe25b0f..f849996 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -412,7 +412,7 @@ void QMessageBoxPrivate::updateSize() void QMessageBoxPrivate::hideSpecial() { Q_Q(QMessageBox); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); QString text = pb->text(); @@ -1266,7 +1266,7 @@ bool QMessageBox::event(QEvent *e) (e->type() == QEvent::OkRequest) ? QApplication::translate("QMessageBox", "OK") : QApplication::translate("QMessageBox", "Help"); - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->text() == bName) { @@ -1513,7 +1513,7 @@ static QMessageBox::StandardButton showNewMessageBox(QWidget *parent, int(defaultButton), 0); QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&msgBox); + QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>(); Q_ASSERT(buttonBox != 0); uint mask = QMessageBox::FirstButton; diff --git a/src/gui/dialogs/qnspanelproxy_mac.mm b/src/gui/dialogs/qnspanelproxy_mac.mm index 0bd5c63..0e8d64d 100644 --- a/src/gui/dialogs/qnspanelproxy_mac.mm +++ b/src/gui/dialogs/qnspanelproxy_mac.mm @@ -42,6 +42,7 @@ #include <qdialogbuttonbox.h> #if defined(Q_WS_MAC) #include <private/qt_mac_p.h> +#include <private/qcocoaintrospection_p.h> #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> #import <objc/objc-class.h> @@ -137,46 +138,6 @@ QT_USE_NAMESPACE QT_BEGIN_NAMESPACE -void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class proxyClass) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - // The following code replaces the _implementation_ for the selector we want to hack - // (originalSel) with the implementation found in proxyClass. Then it creates - // a new 'backup' method inside baseClass containing the old, original, - // implementation (fakeSel). You can let the proxy implementation of originalSel - // call fakeSel if needed (similar approach to calling a super class implementation). - // fakeSel must also be implemented in proxyClass, as the signature is used - // as template for the method one we add into baseClass. - // NB: You will typically never create any instances of proxyClass; we use it - // only for stealing its contents and put it into baseClass. - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method newMethod = class_getInstanceMethod(proxyClass, originalSel); - Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel); - - IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod)); - class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod)); -#endif - } -} - -void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* proxyClass */) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method fakeMethodInBaseClass = class_getInstanceMethod(baseClass, fakeSel); - method_setImplementation(originalMethod, method_getImplementation(fakeMethodInBaseClass)); -#endif - } -} - /* Intercept the NSColorPanel constructor if the shared color panel doesn't exist yet. What's going on here is @@ -188,12 +149,18 @@ void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* pr */ void macStartInterceptNSPanelCtor() { - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); } /* @@ -201,12 +168,14 @@ void macStartInterceptNSPanelCtor() */ void macStopInterceptNSPanelCtor() { - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); } /* @@ -216,8 +185,12 @@ void macStopInterceptNSPanelCtor() void macStartInterceptWindowTitle(QWidget *window) { currentWindow = window; - macStartIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_implementation( + [NSWindow class], + @selector(setTitle:), + [QT_MANGLE_NAMESPACE(QNSWindowProxy) class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* @@ -226,8 +199,10 @@ void macStartInterceptWindowTitle(QWidget *window) void macStopInterceptWindowTitle() { currentWindow = 0; - macStopIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_back_implementation( + [NSWindow class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp index 3fc7f10..4104834 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.cpp +++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp @@ -589,6 +589,18 @@ void QGraphicsGridLayout::removeAt(int index) } /*! + Removes the layout item \a item without destroying it. + Ownership of the item is transferred to the caller. + + \sa addItem() +*/ +void QGraphicsGridLayout::removeItem(QGraphicsLayoutItem *item) +{ + Q_D(QGraphicsGridLayout); + int index = d->engine.indexOf(item); + removeAt(index); +} +/*! \reimp */ void QGraphicsGridLayout::invalidate() diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h index 6580a02..d10235c 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.h +++ b/src/gui/graphicsview/qgraphicsgridlayout.h @@ -109,11 +109,12 @@ public: int columnCount() const; QGraphicsLayoutItem *itemAt(int row, int column) const; - + // inherited from QGraphicsLayout int count() const; QGraphicsLayoutItem *itemAt(int index) const; void removeAt(int index); + void removeItem(QGraphicsLayoutItem *item); void invalidate(); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0b3b164..fdc512e 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1700,12 +1700,12 @@ void QGraphicsItem::setParentItem(QGraphicsItem *newParent) return; const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue<QGraphicsItem *>(newParent))); - newParent = qVariantValue<QGraphicsItem *>(newParentVariant); + QVariant::fromValue<QGraphicsItem *>(newParent))); + newParent = qvariant_cast<QGraphicsItem *>(newParentVariant); if (newParent == d_ptr->parent) return; - const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this)); + const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this)); d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); } @@ -2125,7 +2125,7 @@ void QGraphicsItem::setToolTip(const QString &toolTip) */ QCursor QGraphicsItem::cursor() const { - return qVariantValue<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); + return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); } /*! @@ -2145,8 +2145,8 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue<QCursor>(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant)); + const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor))); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant)); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -2272,7 +2272,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo // Schedule redrawing if (update) { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) c->purge(); if (scene) { @@ -3695,7 +3695,7 @@ void QGraphicsItem::setPos(const QPointF &pos) } // Notify the item that the position is changing. - const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos))); + const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos))); QPointF newPos = newPosVariant.toPointF(); if (newPos == d_ptr->pos) return; @@ -4049,7 +4049,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) if (d_ptr->flags & ItemSendsGeometryChanges) { // Notify the item that the origin point is changing. const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange, - qVariantFromValue<QPointF>(origin))); + QVariant::fromValue<QPointF>(origin))); newOrigin = newOriginVariant.toPointF(); } @@ -4068,7 +4068,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) // Send post-notification. if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin)); + itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin)); } /*! @@ -4330,8 +4330,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) } // Notify the item that the transformation matrix is changing. - const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine()); - newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); + const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine()); + newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); if (d_ptr->transformData->transform == newTransform) return; @@ -4339,7 +4339,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->setTransformHelper(newTransform); // Send post-notification. - itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); + itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform)); } /*! @@ -4380,8 +4380,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Notify the item that the transformation matrix is changing. const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue<QTransform>(newTransform))); - newTransform = qVariantValue<QTransform>(newTransformVariant); + QVariant::fromValue<QTransform>(newTransform))); + newTransform = qvariant_cast<QTransform>(newTransformVariant); if (d_ptr->transformData->transform == newTransform) return; @@ -5234,7 +5234,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c qreal QGraphicsItem::boundingRegionGranularity() const { return d_ptr->hasBoundingRegionGranularity - ? qVariantValue<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) + ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) : 0; } @@ -5270,7 +5270,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) } d_ptr->hasBoundingRegionGranularity = 1; d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity, - qVariantFromValue<qreal>(granularity)); + QVariant::fromValue<qreal>(granularity)); } /*! @@ -5445,7 +5445,7 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) */ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const { - return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); } /*! @@ -5453,11 +5453,11 @@ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const */ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (!c) { QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this); c = new QGraphicsItemCache; - that->setExtra(ExtraCacheData, qVariantFromValue<void *>(c)); + that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c)); } return c; } @@ -5467,7 +5467,7 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const */ void QGraphicsItemPrivate::removeExtraItemCache() { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) { c->purge(); delete c; @@ -8084,6 +8084,8 @@ QPen QAbstractGraphicsShapeItem::pen() const void QAbstractGraphicsShapeItem::setPen(const QPen &pen) { Q_D(QAbstractGraphicsShapeItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; d->boundingRect = QRectF(); @@ -8114,6 +8116,8 @@ QBrush QAbstractGraphicsShapeItem::brush() const void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush) { Q_D(QAbstractGraphicsShapeItem); + if (d->brush == brush) + return; d->brush = brush; update(); } @@ -9244,6 +9248,8 @@ QPen QGraphicsLineItem::pen() const void QGraphicsLineItem::setPen(const QPen &pen) { Q_D(QGraphicsLineItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; update(); diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp index 9cb9a8d..9689616 100644 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp @@ -49,20 +49,20 @@ The QGraphicsItemAnimation class animates a QGraphicsItem. You can schedule changes to the item's transformation matrix at - specified steps. The QGraphicsItemAnimation class has a - current step value. When this value changes the transformations - scheduled at that step are performed. The current step of the + specified steps. The QGraphicsItemAnimation class has a + current step value. When this value changes the transformations + scheduled at that step are performed. The current step of the animation is set with the \c setStep() function. QGraphicsItemAnimation will do a simple linear interpolation - between the nearest adjacent scheduled changes to calculate the + between the nearest adjacent scheduled changes to calculate the matrix. For instance, if you set the position of an item at values 0.0 and 1.0, the animation will show the item moving in a straight - line between these positions. The same is true for scaling and + line between these positions. The same is true for scaling and rotation. It is usual to use the class with a QTimeLine. The timeline's - \l{QTimeLine::}{valueChanged()} signal is then connected to the + \l{QTimeLine::}{valueChanged()} signal is then connected to the \c setStep() slot. For example, you can set up an item for rotation by calling \c setRotationAt() for different step values. The animations timeline is set with the setTimeLine() function. @@ -286,7 +286,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xPosition.size(); ++i) list << QPair<qreal, QPointF>(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value)); - + return list; } @@ -343,7 +343,7 @@ QList<QPair<qreal, qreal> > QGraphicsItemAnimation::rotationList() const QList<QPair<qreal, qreal> > list; for (int i = 0; i < d->rotation.size(); ++i) list << QPair<qreal, qreal>(d->rotation.at(i).step, d->rotation.at(i).value); - + return list; } @@ -395,7 +395,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::translationList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xTranslation.size(); ++i) list << QPair<qreal, QPointF>(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value)); - + return list; } @@ -447,7 +447,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::scaleList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalScale.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value)); - + return list; } @@ -499,7 +499,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::shearList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalShear.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value)); - + return list; } diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 86b4589..91f386f 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE /*! Contructs a QGraphicsLayout object. - + \a parent is passed to QGraphicsLayoutItem's constructor and the QGraphicsLayoutItem's isLayout argument is set to \e true. @@ -259,7 +259,7 @@ void QGraphicsLayout::activate() return; d->activateRecursive(this); - + // we don't call activate on a sublayout, but somebody might. // Therefore, we walk to the parentitem of the toplevel layout. QGraphicsLayoutItem *parentItem = this; @@ -270,7 +270,7 @@ void QGraphicsLayout::activate() Q_ASSERT(!parentItem->isLayout()); setGeometry(parentItem->contentsRect()); // relayout children - + // ### bug, should be parentItem ? parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false // ### too many resizes? maybe we should walk up the chain to the @@ -307,7 +307,7 @@ void QGraphicsLayout::invalidate() // does not call the base implementation? In addition, updateGeometry() // does more than we need. layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); + layoutItem = layoutItem->parentLayoutItem(); } if (layoutItem) layoutItem->d_func()->sizeHintCacheDirty = true; @@ -347,7 +347,7 @@ void QGraphicsLayout::updateGeometry() widget. QGraphicsLayout uses this event handler to listen for layout related events such as geometry changes, layout changes or layout direction changes. - + \a e is a pointer to the event. You can reimplement this event handler to track similar events for your diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp index 88652ec..163fc65 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ b/src/gui/graphicsview/qgraphicslayout_p.cpp @@ -136,13 +136,13 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem /*! \internal - This function is called from subclasses to add a layout item \a layoutItem + This function is called from subclasses to add a layout item \a layoutItem to a layout. It takes care of automatically reparenting graphics items, if needed. If \a layoutItem is a is already in a layout, it will remove it from that layout. - + */ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) { @@ -150,14 +150,14 @@ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) { if (maybeLayout->isLayout()) removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(maybeLayout), layoutItem); - } + } layoutItem->setParentLayoutItem(q); if (layoutItem->isLayout()) { if (QGraphicsItem *parItem = parentItem()) { static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(parItem); } } else { - if (QGraphicsItem *item = layoutItem->graphicsItem()) { + if (QGraphicsItem *item = layoutItem->graphicsItem()) { QGraphicsItem *newParent = parentItem(); QGraphicsItem *oldParent = item->parentItem(); if (oldParent == newParent || !newParent) @@ -182,7 +182,7 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); if (layout->d_func()->activated) layout->invalidate(); - + for (int i = layout->count() - 1; i >= 0; --i) { QGraphicsLayoutItem *childItem = layout->itemAt(i); if (childItem) @@ -194,5 +194,5 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h index 3083555..5c8e706 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ b/src/gui/graphicsview/qgraphicslayout_p.h @@ -84,7 +84,7 @@ class QLayoutStyleInfo public: inline QLayoutStyleInfo() { invalidate(); } inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : m_valid(true), m_style(style), m_widget(widget) + : m_valid(true), m_style(style), m_widget(widget) { Q_ASSERT(style); if (widget) //### @@ -112,7 +112,7 @@ public: return m_defaultSpacing[o - 1]; } - inline qreal perItemSpacing(QSizePolicy::ControlType control1, + inline qreal perItemSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation) const { @@ -132,7 +132,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva Q_DECLARE_PUBLIC(QGraphicsLayout) public: - QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), + QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), activated(true) { } void reparentChildItems(QGraphicsItem *newParent); @@ -148,7 +148,7 @@ public: QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW #endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index 3707591..bfe734a 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -697,7 +697,7 @@ void QGraphicsLayoutItem::setMaximumHeight(qreal height) is equivalent to the item's position in parent coordinates). You must reimplement this function in a subclass of QGraphicsLayoutItem to - receive geometry updates. The layout will call this function when it does a + receive geometry updates. The layout will call this function when it does a rearrangement. If \a rect is outside of the bounds of minimumSize and maximumSize, it diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h index f707c62..cb894a4 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ b/src/gui/graphicsview/qgraphicslayoutitem.h @@ -118,7 +118,7 @@ protected: private: QSizeF *effectiveSizeHints(const QSizeF &constraint) const; Q_DECLARE_PRIVATE(QGraphicsLayoutItem) - + friend class QGraphicsLayout; }; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3c23884..995426f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2548,8 +2548,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(this))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(this))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != this) { if (targetScene && item->d_ptr->scene != targetScene) targetScene->addItem(item); @@ -2960,8 +2960,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(0))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(0))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c8aca80..d568c40 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3709,7 +3709,7 @@ void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect) } /*! - \obsolete + \obsolete Draws the items \a items in the scene using \a painter, after the background and before the foreground are drawn. \a numItems is the number diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 7bd9ecb..62be800 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -62,6 +62,7 @@ #include "qgraphicssceneevent.h" #include <QtGui/qstyleoption.h> #include <private/qabstractscrollarea_p.h> +#include <private/qapplication_p.h> QT_BEGIN_NAMESPACE @@ -180,21 +181,24 @@ public: inline void dispatchPendingUpdateRequests() { -#ifndef Q_WS_MAC - // QWidget::update() works slightly different on the Mac; it's not part of - // our backing store so it needs special threatment. - if (qt_widget_private(viewport)->paintOnScreen()) - QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); - else - QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); -#else - // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) - // is called, which means there's a pending update request. We want to dispatch it - // now because otherwise graphics view updates would require two - // round-trips in the event loop before the item is painted. - extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); - qt_mac_dispatchPendingUpdateRequests(viewport->window()); -#endif +#ifdef Q_WS_MAC + // QWidget::update() works slightly different on the Mac without the raster engine; + // it's not part of our backing store so it needs special threatment. + if (QApplicationPrivate::graphics_system_name != "raster") { + // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) + // is called, which means there's a pending update request. We want to dispatch it + // now because otherwise graphics view updates would require two + // round-trips in the event loop before the item is painted. + extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); + qt_mac_dispatchPendingUpdateRequests(viewport->window()); + } else +#endif // !Q_WS_MAC + { + if (qt_widget_private(viewport)->paintOnScreen()) + QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); + else + QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); + } } void setUpdateClip(QGraphicsItem *); diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index f3b2026..98e6781 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -801,6 +801,15 @@ QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const return q_items.at(index); } +int QGridLayoutEngine::indexOf(QGraphicsLayoutItem *item) const +{ + for (int i = 0; i < q_items.size(); ++i) { + if (item == q_items.at(i)->layoutItem()) + return i; + } + return -1; +} + int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const { ensureEffectiveFirstAndLastRows(); diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index 580af7e..55451d7 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -338,6 +338,7 @@ public: // returns the number of items inserted, which may be less than (rowCount * columnCount) int itemCount() const; QGridLayoutItem *itemAt(int index) const; + int indexOf(QGraphicsLayoutItem *item) const; int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const; int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const; diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ac148ee..300e04b 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2022,6 +2022,88 @@ void QImage::fill(uint pixel) 0, 0, d->width, d->height, d->bytes_per_line); } + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + \since 4.8 + */ + +void QImage::fill(Qt::GlobalColor color) +{ + fill(QColor(color)); +} + + + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + Fills the entire image with the given \a color. + + If the depth of the image is 1, the image will be filled with 1 if + \a color equals Qt::color0; it will otherwise be filled with 0. + + If the depth of the image is 8, the image will be filled with the + index corresponding the \a color in the color table if present; it + will otherwise be filled with 0.| + + \since 4.8 +*/ + +void QImage::fill(const QColor &color) +{ + if (!d) + return; + detach(); + + // In case we run out of memory + if (!d) + return; + + if (d->depth == 32) { + uint pixel = color.rgba(); + if (d->format == QImage::Format_ARGB32_Premultiplied) + pixel = PREMUL(pixel); + fill((uint) pixel); + + } else if (d->depth == 16 && d->format == QImage::Format_RGB16) { + qrgb565 p(color.rgba()); + fill((uint) p.rawValue()); + + } else if (d->depth == 1) { + if (color == Qt::color1) + fill((uint) 1); + else + fill((uint) 0); + + } else if (d->depth == 8) { + uint pixel = 0; + for (int i=0; i<d->colortable.size(); ++i) { + if (color.rgba() == d->colortable.at(i)) { + pixel = i; + break; + } + } + fill(pixel); + + } else { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(rect(), color); + } + +} + + + + + + /*! Inverts all pixel values in the image. diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 896061f..f37dcf2 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -210,6 +210,9 @@ public: void setColorTable(const QVector<QRgb> colors); void fill(uint pixel); + void fill(const QColor &color); + void fill(Qt::GlobalColor color); + bool hasAlphaChannel() const; void setAlphaChannel(const QImage &alphaChannel); diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index ec56af2..03ee902 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1092,7 +1092,7 @@ QColor QImageReader::backgroundColor() const if (!d->initHandler()) return QColor(); if (d->handler->supportsOption(QImageIOHandler::BackgroundColor)) - return qVariantValue<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); + return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); return QColor(); } diff --git a/src/gui/image/qmnghandler.cpp b/src/gui/image/qmnghandler.cpp index cf53af0..40f1b54 100644 --- a/src/gui/image/qmnghandler.cpp +++ b/src/gui/image/qmnghandler.cpp @@ -481,7 +481,7 @@ void QMngHandler::setOption(ImageOption option, const QVariant & value) { Q_D(QMngHandler); if (option == QImageIOHandler::BackgroundColor) - d->setBackgroundColor(qVariantValue<QColor>(value)); + d->setBackgroundColor(qvariant_cast<QColor>(value)); } /*! \reimp */ diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index c039ca8..d5db431 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -99,7 +99,7 @@ static bool qt_pixmap_thread_test() return false; } #ifndef Q_WS_WIN - if (qApp->thread() != QThread::currentThread()) { + if (!QApplication::testAttribute(Qt::AA_X11InitThreads) && qApp->thread() != QThread::currentThread()) { qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread"); return false; } diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 3d9c363..9f8e643 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -310,7 +310,7 @@ static int defaultScreen = -1; QPixmap member functions *****************************************************************************/ -static int qt_pixmap_serial = 0; +QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0); int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0; QX11PixmapData::QX11PixmapData(PixelType type) @@ -327,7 +327,7 @@ QPixmapData *QX11PixmapData::createCompatiblePixmapData() const void QX11PixmapData::resize(int width, int height) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = width; h = height; @@ -410,7 +410,7 @@ struct QX11AlphaDetector void QX11PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = img.width(); h = img.height(); @@ -2014,7 +2014,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform, x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), w, h, d); - x11Data->setSerialNumber(++qt_pixmap_serial); + x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); #ifndef QT_NO_XRENDER if (X11->use_xrender) { @@ -2265,7 +2265,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect) const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data); - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); flags &= ~Uninitialized; xinfo = x11Data->xinfo; @@ -2385,7 +2385,7 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) } QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType); - data->setSerialNumber(++qt_pixmap_serial); + data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); data->flags = QX11PixmapData::Readonly; data->share_mode = mode; data->w = width; diff --git a/src/gui/itemviews/qabstractitemdelegate.cpp b/src/gui/itemviews/qabstractitemdelegate.cpp index 0ea6d67..edbeeb8 100644 --- a/src/gui/itemviews/qabstractitemdelegate.cpp +++ b/src/gui/itemviews/qabstractitemdelegate.cpp @@ -362,7 +362,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::ToolTip: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant tooltip = index.data(Qt::ToolTipRole); - if (qVariantCanConvert<QString>(tooltip)) { + if (tooltip.canConvert<QString>()) { QToolTip::showText(he->globalPos(), tooltip.toString(), view); return true; } @@ -376,7 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::WhatsThis: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant whatsthis = index.data(Qt::WhatsThisRole); - if (qVariantCanConvert<QString>(whatsthis)) { + if (whatsthis.canConvert<QString>()) { QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view); return true; } diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 4ffd284..12add05 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -79,6 +79,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() pressedAlreadySelected(false), viewportEnteredNeeded(false), state(QAbstractItemView::NoState), + stateBeforeAnimation(QAbstractItemView::NoState), editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed), lastTrigger(QAbstractItemView::NoEditTriggers), tabKeyNavigation(false), @@ -652,7 +653,7 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) "QAbstractItemView::setModel", "A model should return the exact same index " "(including its internal id/pointer) when asked for it twice in a row."); - Q_ASSERT_X(d->model->index(0,0).parent() == QModelIndex(), + Q_ASSERT_X(!d->model->index(0,0).parent().isValid(), "QAbstractItemView::setModel", "The parent of a top level index should be invalid"); @@ -2945,7 +2946,7 @@ int QAbstractItemView::sizeHintForRow(int row) const { Q_D(const QAbstractItemView); - if (row < 0 || row >= d->model->rowCount() || !model()) + if (row < 0 || row >= d->model->rowCount(d->root)) return -1; ensurePolished(); @@ -2957,7 +2958,7 @@ int QAbstractItemView::sizeHintForRow(int row) const for (int c = 0; c < colCount; ++c) { index = d->model->index(row, c, d->root); if (QWidget *editor = d->editorForIndex(index).editor) - height = qMax(height, editor->size().height()); + height = qMax(height, editor->height()); int hint = d->delegateForIndex(index)->sizeHint(option, index).height(); height = qMax(height, hint); } @@ -2976,7 +2977,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const { Q_D(const QAbstractItemView); - if (column < 0 || column >= d->model->columnCount() || !model()) + if (column < 0 || column >= d->model->columnCount(d->root)) return -1; ensurePolished(); diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index fce74f3..969553a 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -135,8 +135,9 @@ public: } void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} - - bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#ifndef QT_NO_DRAGANDDROP + virtual bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#endif bool droppingOnItself(QDropEvent *event, const QModelIndex &index); QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options); @@ -367,6 +368,7 @@ public: bool viewportEnteredNeeded; QAbstractItemView::State state; + QAbstractItemView::State stateBeforeAnimation; QAbstractItemView::EditTriggers editTriggers; QAbstractItemView::EditTrigger lastTrigger; diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp index 43a1327..4d4b3d8 100644 --- a/src/gui/itemviews/qabstractproxymodel.cpp +++ b/src/gui/itemviews/qabstractproxymodel.cpp @@ -45,6 +45,9 @@ #include "qitemselectionmodel.h" #include <private/qabstractproxymodel_p.h> +#include <QtCore/QSize> +#include <QtCore/QStringList> + QT_BEGIN_NAMESPACE @@ -262,6 +265,15 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu /*! \reimp */ +bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) +{ + Q_D(QAbstractProxyModel); + return d->model->setItemData(mapToSource(index), roles); +} + +/*! + \reimp + */ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { Q_D(QAbstractProxyModel); @@ -276,6 +288,90 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation return d->model->setHeaderData(sourceSection, orientation, value, role); } +/*! + \reimp + */ +QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return mapFromSource(d->model->buddy(mapToSource(index))); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->canFetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::fetchMore(const QModelIndex &parent) +{ + Q_D(QAbstractProxyModel); + d->model->fetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::sort(int column, Qt::SortOrder order) +{ + Q_D(QAbstractProxyModel); + d->model->sort(column, order); +} + +/*! + \reimp + */ +QSize QAbstractProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return d->model->span(mapToSource(index)); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->hasChildren(mapToSource(parent)); +} + +/*! + \reimp + */ +QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const +{ + Q_D(const QAbstractProxyModel); + QModelIndexList list; + foreach(const QModelIndex &index, indexes) + list << mapToSource(index); + return d->model->mimeData(indexes); +} + +/*! + \reimp + */ +QStringList QAbstractProxyModel::mimeTypes() const +{ + Q_D(const QAbstractProxyModel); + return d->model->mimeTypes(); +} + +/*! + \reimp + */ +Qt::DropActions QAbstractProxyModel::supportedDropActions() const +{ + Q_D(const QAbstractProxyModel); + return d->model->supportedDropActions(); +} + QT_END_NAMESPACE #include "moc_qabstractproxymodel.cpp" diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h index c6bb985..a5a1168 100644 --- a/src/gui/itemviews/qabstractproxymodel.h +++ b/src/gui/itemviews/qabstractproxymodel.h @@ -81,8 +81,20 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QModelIndex buddy(const QModelIndex &index) const; + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + QSize span(const QModelIndex &index) const; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + QMimeData* mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + Qt::DropActions supportedDropActions() const; + protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index 67854a3..7eb3ddc 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -2105,7 +2105,7 @@ void QHeaderView::paintEvent(QPaintEvent *e) QVariant variant = d->model->headerData(logical, d->orientation, Qt::FontRole); - if (variant.isValid() && qVariantCanConvert<QFont>(variant)) { + if (variant.isValid() && variant.canConvert<QFont>()) { QFont sectionFont = qvariant_cast<QFont>(variant); painter.setFont(sectionFont); } @@ -2485,13 +2485,13 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical opt.icon = qvariant_cast<QPixmap>(variant); QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(foregroundBrush)) + if (foregroundBrush.canConvert<QBrush>()) opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush)); QPointF oldBO = painter->brushOrigin(); QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(backgroundBrush)) { + if (backgroundBrush.canConvert<QBrush>()) { opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush)); opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush)); painter->setBrushOrigin(opt.rect.topLeft()); @@ -2552,7 +2552,7 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const QVariant var = d->model->headerData(logicalIndex, d->orientation, Qt::FontRole); QFont fnt; - if (var.isValid() && qVariantCanConvert<QFont>(var)) + if (var.isValid() && var.canConvert<QFont>()) fnt = qvariant_cast<QFont>(var); else fnt = font(); diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 9bbfc23..bd2b401 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -850,7 +850,7 @@ void QItemDelegate::drawBackground(QPainter *painter, painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); } else { QVariant value = index.data(Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { QPointF oldBO = painter->brushOrigin(); painter->setBrushOrigin(option.rect.topLeft()); painter->fillRect(option.rect, qvariant_cast<QBrush>(value)); @@ -1326,7 +1326,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index, // set foreground brush value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); return opt; diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index f848321..7156b87 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -212,6 +212,7 @@ bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const { return (isValid() && other.isValid() && parent() == other.parent() + && model() == other.model() && ((top() <= other.top() && bottom() >= other.top()) || (top() >= other.top() && top() <= other.bottom())) && ((left() <= other.left() && right() >= other.left()) @@ -508,7 +509,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel void QItemSelection::split(const QItemSelectionRange &range, const QItemSelectionRange &other, QItemSelection *result) { - if (range.parent() != other.parent()) + if (range.parent() != other.parent() || range.model() != other.model()) return; QModelIndex parent = other.parent(); @@ -634,6 +635,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare } QItemSelection deselected; + QItemSelection newParts; QItemSelection::iterator it = ranges.begin(); while (it != ranges.end()) { if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range @@ -659,13 +661,20 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight())); *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent())); ++it; - } else { - if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing) - deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), - model->index(end, it->left(), it->parent()))); + } else if (it->top() < start && end < it->bottom()) { // Middle intersection + // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected, + // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6]. + // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection + // in ranges. + const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()), + model->index(end, it->left(), it->parent())); + deselected.append(removedRange); + QItemSelection::split(*it, removedRange, &newParts); + it = ranges.erase(it); + } else ++it; - } } + ranges.append(newParts); if (!deselected.isEmpty()) emit q->selectionChanged(QItemSelection(), deselected); diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h index 436514f..e2bd06b 100644 --- a/src/gui/itemviews/qitemselectionmodel.h +++ b/src/gui/itemviews/qitemselectionmodel.h @@ -101,6 +101,30 @@ public: { return (tl == other.tl && br == other.br); } inline bool operator!=(const QItemSelectionRange &other) const { return !operator==(other); } + inline bool operator<(const QItemSelectionRange &other) const + { + // Comparing parents will compare the models, but if two equivalent ranges + // in two different models have invalid parents, they would appear the same + if (other.tl.model() == tl.model()) { + // parent has to be calculated, so we only do so once. + const QModelIndex topLeftParent = tl.parent(); + const QModelIndex otherTopLeftParent = other.tl.parent(); + if (topLeftParent == otherTopLeftParent) { + if (other.tl.row() == tl.row()) { + if (other.tl.column() == tl.column()) { + if (other.br.row() == br.row()) { + return br.column() < other.br.column(); + } + return br.row() < other.br.row(); + } + return tl.column() < other.tl.column(); + } + return tl.row() < other.tl.row(); + } + return topLeftParent < otherTopLeftParent; + } + return tl.model() < other.tl.model(); + } inline bool isValid() const { diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 76d7642..ce1f0e5 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -756,10 +756,13 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e // if the parent is above d->root in the tree, nothing will happen QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); if (parent == d->root) { - for (int i = d->hiddenRows.count() - 1; i >= 0; --i) { - int hiddenRow = d->hiddenRows.at(i).row(); + QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin(); + while (it != d->hiddenRows.end()) { + int hiddenRow = it->row(); if (hiddenRow >= start && hiddenRow <= end) { - d->hiddenRows.remove(i); + it = d->hiddenRows.erase(it); + } else { + ++it; } } } @@ -1033,16 +1036,7 @@ void QListView::paintEvent(QPaintEvent *e) previousRow = row; } - if (const QWidget *widget = d->editorForIndex(*it).editor) { - QRegion itemGeometry(option.rect); - QRegion widgetGeometry(widget->geometry()); - painter.save(); - painter.setClipRegion(itemGeometry.subtracted(widgetGeometry)); - d->delegateForIndex(*it)->paint(&painter, option, *it); - painter.restore(); - } else { - d->delegateForIndex(*it)->paint(&painter, option, *it); - } + d->delegateForIndex(*it)->paint(&painter, option, *it); } #ifndef QT_NO_DRAGANDDROP @@ -1833,6 +1827,14 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint else return QAbstractItemViewPrivate::position(pos, rect, idx); } + +bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex); + else + return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex); +} #endif /* @@ -1841,12 +1843,12 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint void QCommonListViewBase::appendHiddenRow(int row) { - dd->hiddenRows.append(dd->model->index(row, 0, qq->rootIndex())); + dd->hiddenRows.insert(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::removeHiddenRow(int row) { - dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0, qq->rootIndex()))); + dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) @@ -1960,7 +1962,13 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) // ignore by default event->ignore(); - QModelIndex index = qq->indexAt(event->pos()); + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + QModelIndex index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); dd->hover = index; if (!dd->droppingOnItself(event, index) && dd->canDecode(event)) { @@ -1968,10 +1976,11 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) if (index.isValid() && dd->showDropIndicator) { QRect rect = qq->visualRect(index); dd->dropIndicatorPosition = position(event->pos(), rect, index); + // if spacing, should try to draw between items, not just next to item. switch (dd->dropIndicatorPosition) { case QAbstractItemView::AboveItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -1979,7 +1988,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) break; case QAbstractItemView::BelowItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -2014,6 +2023,68 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) qq->startAutoScroll(); } +/*! + If the event hasn't already been accepted, determines the index to drop on. + + if (row == -1 && col == -1) + // append to this drop index + else + // place at row, col in drop index + + If it returns true a drop can be done, and dropRow, dropCol and dropIndex reflects the position of the drop. + \internal + */ +bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (event->isAccepted()) + return false; + + QModelIndex index; + if (dd->viewport->rect().contains(event->pos())) { + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); + if (!index.isValid()) + index = dd->root; + } + + // If we are allowed to do the drop + if (dd->model->supportedDropActions() & event->dropAction()) { + int row = -1; + int col = -1; + if (index != dd->root) { + dd->dropIndicatorPosition = position(event->pos(), qq->visualRect(index), index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + row = index.row(); + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::BelowItem: + row = index.row() + 1; + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::OnItem: + case QAbstractItemView::OnViewport: + break; + } + } else { + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + } + *dropIndex = index; + *dropRow = row; + *dropCol = col; + if (!dd->droppingOnItself(event, index)) + return true; + } + return false; +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) @@ -2107,7 +2178,7 @@ int QListModeViewBase::verticalOffset() const int value = verticalScrollBar()->value(); if (value >= segmentPositions.count()) return 0; - return segmentPositions.at(value); + return segmentPositions.at(value) - spacing(); } } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { int value = verticalScrollBar()->value(); @@ -2155,14 +2226,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) if (horizontal && flow() == QListView::TopToBottom && dx != 0) { int currentValue = qBound(0, horizontalValue, max); int previousValue = qBound(0, currentValue + dx, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dx = previousCoordinate - currentCoordinate; } else if (vertical && flow() == QListView::LeftToRight && dy != 0) { int currentValue = qBound(0, verticalValue, max); int previousValue = qBound(0, currentValue + dy, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dy = previousCoordinate - currentCoordinate; } } else { @@ -2330,6 +2401,8 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) segmentExtents.append(flowPosition); flowPosition = info.spacing + segStartPosition; segPosition += deltaSegPosition; + if (info.wrap) + segPosition += info.spacing; segmentPositions.append(segPosition); segmentStartRows.append(row); deltaSegPosition = 0; diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index bf7657b..1b71131 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -237,6 +237,7 @@ public: // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}. QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; void dragMoveEvent(QDragMoveEvent *e); + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif private: @@ -364,6 +365,7 @@ public: #ifndef QT_NO_DRAGANDDROP virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif inline void setGridSize(const QSize &size) { grid = size; } @@ -376,7 +378,10 @@ public: inline bool isSelectionRectVisible() const { return showElasticBand; } inline QModelIndex modelIndex(int row) const { return model->index(row, column, root); } - inline bool isHidden(int row) const { return hiddenRows.contains(model->index(row, 0, root)); } + inline bool isHidden(int row) const { + QModelIndex idx = model->index(row, 0, root); + return isPersistent(idx) && hiddenRows.contains(idx); + } inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); } inline void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex ¤t) const { @@ -430,7 +435,7 @@ public: QBasicTimer batchLayoutTimer; // used for hidden items - QVector<QPersistentModelIndex> hiddenRows; + QSet<QPersistentModelIndex> hiddenRows; int column; bool uniformItemSizes; diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 880f8ab..115c734 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -326,7 +326,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option, option->displayAlignment = Qt::Alignment(value.toInt()); value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) { diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 4492e53..e9e2e38 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -926,14 +926,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q); - if (const QWidget *widget = editorForIndex(index).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - q->itemDelegate(index)->paint(painter, opt, index); - painter->restore(); - } else { - q->itemDelegate(index)->paint(painter, opt, index); - } + q->itemDelegate(index)->paint(painter, opt, index); } /*! diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index b797776..ccc8e00 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1669,14 +1669,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, opt.state = oldState; } - if (const QWidget *widget = d->editorForIndex(modelIndex).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - painter->restore(); - } else { - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - } + d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); } if (currentRowHasFocus) { @@ -2469,11 +2462,9 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) } const int parentItem = d->viewIndex(parent); - if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled()) + if (((parentItem != -1) && d->viewItems.at(parentItem).expanded) || (parent == d->root)) { d->doDelayedItemsLayout(); - } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) { - d->doDelayedItemsLayout(); } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) { // the parent just went from 0 children to more. update to re-paint the decoration d->viewItems[parentItem].hasChildren = true; @@ -2870,13 +2861,13 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (emitSignal && animationsEnabled) prepareAnimatedOperation(item, QVariantAnimation::Forward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::ExpandingState); const QModelIndex index = viewItems.at(item).index; storeExpanded(index); viewItems[item].expanded = true; layout(item); - q->setState(oldState); + q->setState(stateBeforeAnimation); if (model->canFetchMore(index)) model->fetchMore(index); @@ -2945,7 +2936,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) prepareAnimatedOperation(item, QVariantAnimation::Backward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::CollapsingState); expandedIndexes.erase(it); viewItems[item].expanded = false; @@ -2955,7 +2946,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) index = viewItems[index].parentItem; } removeViewItems(item + 1, total); // collapse - q->setState(oldState); + q->setState(stateBeforeAnimation); if (emitSignal) { emit q->collapsed(modelIndex); @@ -3066,7 +3057,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons void QTreeViewPrivate::_q_endAnimatedOperation() { Q_Q(QTreeView); - q->setState(QAbstractItemView::NoState); + q->setState(stateBeforeAnimation); q->updateGeometries(); viewport->update(); } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f9c84c1..2629d7f 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -216,7 +216,8 @@ embedded { qcocoaapplicationdelegate_mac_p.h \ qmacgesturerecognizer_mac_p.h \ qmultitouch_mac_p.h \ - qcocoasharedwindowmethods_mac_p.h + qcocoasharedwindowmethods_mac_p.h \ + qcocoaintrospection_p.h OBJECTIVE_SOURCES += \ kernel/qcursor_mac.mm \ @@ -236,7 +237,8 @@ embedded { kernel/qeventdispatcher_mac.mm \ kernel/qcocoawindowcustomthemeframe_mac.mm \ kernel/qmacgesturerecognizer_mac.mm \ - kernel/qmultitouch_mac.mm + kernel/qmultitouch_mac.mm \ + kernel/qcocoaintrospection_mac.mm HEADERS += \ kernel/qt_cocoa_helpers_mac_p.h \ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 3d3a749..d9c3b6a 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -148,8 +148,6 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT void qt_call_post_routines(); -int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 - QApplication::Type qt_appType=QApplication::Tty; QApplicationPrivate *QApplicationPrivate::self = 0; @@ -164,8 +162,8 @@ bool QApplicationPrivate::autoSipEnabled = false; bool QApplicationPrivate::autoSipEnabled = true; #endif -QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) - : QCoreApplicationPrivate(argc, argv) +QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags) + : QCoreApplicationPrivate(argc, argv, flags) { application_type = type; qt_appType = type; @@ -704,12 +702,12 @@ void QApplicationPrivate::process_cmdline() */ QApplication::QApplication(int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) +{ Q_D(QApplication); d->construct(); } /*! @@ -738,12 +736,12 @@ QApplication::QApplication(int &argc, char **argv, int _internal) */ QApplication::QApplication(int &argc, char **argv, bool GUIenabled ) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, _internal)) +{ Q_D(QApplication); d->construct();} @@ -761,12 +759,12 @@ QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _intern \c -qws option). */ QApplication::QApplication(int &argc, char **argv, Type type) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, Type type , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, _internal)) +{ Q_D(QApplication); d->construct(); } /*! @@ -846,7 +844,7 @@ static char *aargv[] = { (char*)"unknown", 0 }; This function is only available on X11. */ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -855,7 +853,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) } QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -880,7 +878,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, */ QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -890,7 +888,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -3693,11 +3691,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (e->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(e)->child()); -#endif // QT3_SUPPORT - // capture the current mouse/keyboard state if(e->spontaneous()) { if (e->type() == QEvent::KeyPress @@ -5798,12 +5791,12 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, #ifndef QT_NO_GESTURES QGestureManager* QGestureManager::instance() { - if (QApplicationPrivate *qAppPriv = QApplicationPrivate::instance()) { - if (!qAppPriv->gestureManager) - qAppPriv->gestureManager = new QGestureManager(qApp); - return qAppPriv->gestureManager; - } - return 0; + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (!qAppPriv) + return 0; + if (!qAppPriv->gestureManager) + qAppPriv->gestureManager = new QGestureManager(qApp); + return qAppPriv->gestureManager; } #endif // QT_NO_GESTURES diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 0242582..a790c69 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -123,15 +123,15 @@ public: #endif #ifndef qdoc - QApplication(int &argc, char **argv, int = QT_VERSION); - QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION); - QApplication(int &argc, char **argv, Type, int = QT_VERSION); + QApplication(int &argc, char **argv, int = ApplicationFlags); + QApplication(int &argc, char **argv, bool GUIenabled, int = ApplicationFlags); + QApplication(int &argc, char **argv, Type, int = ApplicationFlags); #if defined(Q_WS_X11) - QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION); - QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION); + QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = ApplicationFlags); + QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = ApplicationFlags); #endif #if defined(Q_OS_SYMBIAN) - QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = QT_VERSION); + QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = ApplicationFlags); #endif #endif virtual ~QApplication(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 321492d..afd7c4b 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1246,6 +1246,8 @@ void qt_init(QApplicationPrivate *priv, int) // Cocoa application delegate #ifdef QT_MAC_USE_COCOA NSApplication *cocoaApp = [QNSApplication sharedApplication]; + qt_redirectNSApplicationSendEvent(); + QMacCocoaAutoReleasePool pool; NSObject *oldDelegate = [cocoaApp delegate]; QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; @@ -2611,25 +2613,26 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap /*! \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event) - \warning This virtual function is only implemented under Mac OS X when against Carbon. + \warning This virtual function is only used under Mac OS X, and behaves different + depending on if Qt is based on Carbon or Cocoa. - If you create an application that inherits QApplication and reimplement + For the Carbon port, If you create an application that inherits QApplication and reimplement this function, you get direct access to all Carbon Events that Qt registers for from Mac OS X with this function being called with the \a caller and the \a event. + For the Cocoa port, If you create an application that inherits QApplication and reimplement + this function, you get direct access to all Cocoa Events that Qt receives + from Mac OS X with this function being called with the \a caller being 0 and + the \a event being an NSEvent pointer: + + NSEvent *e = reinterpret_cast<NSEvent *>(event); + Return true if you want to stop the event from being processed. Return false for normal event dispatching. The default implementation returns false. - Cocoa uses a different event system which means this function is NOT CALLED - when building Qt against Cocoa. If you want similar functionality subclass - NSApplication and reimplement the sendEvent: message to handle all the - NSEvents. You also will need to to instantiate your custom NSApplication - before creating a QApplication. See \l - {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's - NSApplication Reference} for more information. - + \sa macEventFilter(void *nsevent) */ bool QApplication::macEventFilter(EventHandlerCallRef, EventRef) { @@ -3110,11 +3113,7 @@ void onApplicationChangedActivation( bool activated ) } if (!app->activeWindow()) { -#if QT_MAC_USE_COCOA - OSWindowRef wp = [NSApp keyWindow]; -#else - OSWindowRef wp = ActiveNonFloatingWindow(); -#endif + OSWindowRef wp = [NSApp keyWindow]; if (QWidget *tmp_w = qt_mac_find_window(wp)) app->setActiveWindow(tmp_w); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 8dc16e0..5f200c0 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -291,7 +291,7 @@ class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate { Q_DECLARE_PUBLIC(QApplication) public: - QApplicationPrivate(int &argc, char **argv, QApplication::Type type); + QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags); ~QApplicationPrivate(); #if defined(Q_WS_X11) @@ -489,8 +489,6 @@ public: static QString styleOverride; - static int app_compile_version; - #ifdef QT_KEYPAD_NAVIGATION static QWidget *oldEditFocus; static Qt::NavigationMode navigationMode; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 7c5e790..5c1f29e 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1367,7 +1367,7 @@ void QSymbianControl::setFocusSafely(bool focus) This function is only available on S60. */ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; @@ -1375,7 +1375,7 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int } QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 0c48bfd..11db75b 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -207,8 +207,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); } } @@ -946,29 +944,36 @@ bool qt_nograb() // application no-grab option typedef QHash<QString, int> WinClassNameHash; Q_GLOBAL_STATIC(WinClassNameHash, winclassNames) +// +// If 0 is passed as the widget pointer, register a window class +// for QWidget as default. This is used in QGLTemporaryContext +// during GL initialization, where we don't want to use temporary +// QWidgets or QGLWidgets, neither do we want to have separate code +// to register window classes. +// const QString qt_reg_winclass(QWidget *w) // register window class { - int flags = w->windowFlags(); + int flags = w ? w->windowFlags() : 0; int type = flags & Qt::WindowType_Mask; uint style; bool icon; QString cname; - if (qt_widget_private(w)->isGLWidget) { + if (w && qt_widget_private(w)->isGLWidget) { cname = QLatin1String("QGLWidget"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (flags & Qt::MSWindowsOwnDC) { + } else if (w && (flags & Qt::MSWindowsOwnDC)) { cname = QLatin1String("QWidgetOwnDC"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (type == Qt::Tool || type == Qt::ToolTip){ + } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) { style = CS_DBLCLKS; if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP @@ -983,7 +988,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class style |= CS_SAVEBITS; #endif icon = false; - } else if (type == Qt::Popup) { + } else if (w && (type == Qt::Popup)) { cname = QLatin1String("QPopup"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE @@ -1054,7 +1059,10 @@ const QString qt_reg_winclass(QWidget *w) // register window class } wc.hCursor = 0; #ifndef Q_WS_WINCE - wc.hbrBackground = qt_widget_private(w)->isGLWidget ? 0 : (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + HBRUSH brush = 0; + if (w && !qt_widget_private(w)->isGLWidget) + brush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + wc.hbrBackground = brush; #else wc.hbrBackground = 0; #endif @@ -1076,8 +1084,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class Q_GUI_EXPORT const QString qt_getRegisteredWndClass() { - QWidget w; - return qt_reg_winclass(&w); + return qt_reg_winclass(0); } static void unregWinClasses() @@ -3678,13 +3685,11 @@ static void initWinTabFunctions() return; QLibrary library(QLatin1String("wintab32")); - if (library.load()) { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); - ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); - ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); - } + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); + ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); + ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); + ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); #endif // Q_OS_WINCE } #endif // QT_NO_TABLETEVENT diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index e4d9848..3a7858c 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -456,11 +456,9 @@ static void* qt_load_library_runtime(const char *library, int vernum, Q_FOREACH(int version, versions) { QLatin1String libName(library); QLibrary xfixesLib(libName, version); - if (xfixesLib.load()) { - void *ptr = xfixesLib.resolve(symbol); - if (ptr) - return ptr; - } + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; } return 0; } @@ -1712,6 +1710,9 @@ void qt_init(QApplicationPrivate *priv, int, } else { // Qt controls everything (default) + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + XInitThreads(); + // Set application name and class char *app_class = 0; if (argv && argv[0]) { @@ -2557,22 +2558,20 @@ void qt_init(QApplicationPrivate *priv, int, #if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET) QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this. - if (wacom.load()) { - // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x - ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); - ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); - ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); - ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); - ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); - - if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 - || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. + // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x + ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); + ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); + ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); + ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); + ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); + + if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 + || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. ptrWacomConfigInit = 0; ptrWacomConfigOpenDevice = 0; ptrWacomConfigGetRawParam = 0; ptrWacomConfigCloseDevice = 0; ptrWacomConfigTerm = 0; - } } #endif } diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index f7c0b6e..8c7c333 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -631,7 +631,7 @@ QByteArray QMimeDataWrapper::encodedData(const char *format) const return data->data(QLatin1String(format)); } else{ QVariant variant = data->imageData(); - QImage img = qVariantValue<QImage>(variant); + QImage img = qvariant_cast<QImage>(variant); QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index 4962863..9270213 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -78,6 +78,7 @@ #include <private/qcocoaapplication_mac_p.h> #include <private/qcocoaapplicationdelegate_mac_p.h> #include <private/qt_cocoa_helpers_mac_p.h> +#include <private/qcocoaintrospection_p.h> QT_USE_NAMESPACE @@ -116,12 +117,30 @@ QT_USE_NAMESPACE quint64 lower = [event data1]; quint64 upper = [event data2]; QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32)); - [args->target performSelector:args->selector]; + // Special case for convenience: if the argument is an NSNumber, we unbox it directly. + // Use NSValue instead if this behaviour is unwanted. + id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 intValue] : args->arg1; + id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 intValue] : args->arg2; + switch (args->argCount) { + case 0: + [args->target performSelector:args->selector]; + break; + case 1: + [args->target performSelector:args->selector withObject:a1]; + break; + case 3: + [args->target performSelector:args->selector withObject:a1 withObject:a2]; + break; + } + delete args; } -- (BOOL)qt_sendEvent:(NSEvent *)event +- (BOOL)qt_filterEvent:(NSEvent *)event { + if (qApp->macEventFilter(0, reinterpret_cast<EventRef>(event))) + return true; + if ([event type] == NSApplicationDefined) { switch ([event subtype]) { case QtCocoaEventSubTypePostMessage: @@ -138,20 +157,55 @@ QT_USE_NAMESPACE @implementation QNSApplication -// WARNING: If Qt did not create NSApplication (this can e.g. -// happend if Qt is used as a plugin from a 3rd-party cocoa -// application), QNSApplication::sendEvent will never be called. -// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE. -// Plugin developers that _do_ control the NSApplication sub-class -// implementation of the 3rd-party application can call qt_sendEvent -// from the sub-class event handler (like we do here) to work around -// any issues. +- (void)qt_sendEvent_original:(NSEvent *)event +{ + Q_UNUSED(event); + // This method will only be used as a signature + // template for the method we add into NSApplication + // containing the original [NSApplication sendEvent:] implementation +} + +- (void)qt_sendEvent_replacement:(NSEvent *)event +{ + // This method (or its implementation to be precise) will + // be called instead of sendEvent if redirection occurs. + // 'self' will then be an instance of NSApplication + // (and not QNSApplication) + if (![NSApp qt_filterEvent:event]) + [self qt_sendEvent_original:event]; +} + - (void)sendEvent:(NSEvent *)event { - if (![self qt_sendEvent:event]) + // This method will be called if + // no redirection occurs + if (![NSApp qt_filterEvent:event]) [super sendEvent:event]; } @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent() +{ + if ([NSApp isMemberOfClass:[QNSApplication class]]) { + // No need to change implementation since Qt + // already controls a subclass of NSApplication + return; + } + + // Change the implementation of [NSApplication sendEvent] to the + // implementation of qt_sendEvent_replacement found in QNSApplication. + // And keep the old implementation that gets overwritten inside a new + // method 'qt_sendEvent_original' that we add to NSApplication + qt_cocoa_change_implementation( + [NSApplication class], + @selector(sendEvent:), + [QNSApplication class], + @selector(qt_sendEvent_replacement:), + @selector(qt_sendEvent_original:)); + } + +QT_END_NAMESPACE #endif diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h index 5569feb..c89ff36 100644 --- a/src/gui/kernel/qcocoaapplication_mac_p.h +++ b/src/gui/kernel/qcocoaapplication_mac_p.h @@ -101,11 +101,17 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) - (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; - (void)qt_sendPostedMessage:(NSEvent *)event; -- (BOOL)qt_sendEvent:(NSEvent *)event; +- (BOOL)qt_filterEvent:(NSEvent *)event; @end @interface QNSApplication : NSApplication { } @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent(); + +QT_END_NAMESPACE + #endif diff --git a/src/gui/kernel/qcocoaintrospection_mac.mm b/src/gui/kernel/qcocoaintrospection_mac.mm new file mode 100644 index 0000000..9b536b7 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_mac.mm @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <private/qcocoaintrospection_p.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // The following code replaces the _implementation_ for the selector we want to hack + // (originalSel) with the implementation found in proxyClass. Then it creates + // a new 'backup' method inside baseClass containing the old, original, + // implementation (fakeSel). You can let the proxy implementation of originalSel + // call fakeSel if needed (similar approach to calling a super class implementation). + // fakeSel must also be implemented in proxyClass, as the signature is used + // as template for the method one we add into baseClass. + // NB: You will typically never create any instances of proxyClass; we use it + // only for stealing its contents and put it into baseClass. + if (!replacementSel) + replacementSel = originalSel; + + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); + IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); + + if (backupSel) { + Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); + class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); + } +#endif + } +} + +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); + method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); +#endif + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoaintrospection_p.h b/src/gui/kernel/qcocoaintrospection_p.h new file mode 100644 index 0000000..b9422e8 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <qglobal.h> +#import <objc/objc-class.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0); +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel); + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 6795149..430a661 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -153,17 +153,6 @@ QT_END_NAMESPACE - (void)sendEvent:(NSEvent *)event { - if ([event type] == NSApplicationDefined) { - switch ([event subtype]) { - case QtCocoaEventSubTypePostMessage: - [NSApp qt_sendPostedMessage:event]; - return; - default: - break; - } - return; - } - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; // Cocoa can hold onto the window after we've disavowed its knowledge. So, // if we get sent an event afterwards just have it go through the super's diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index a552ce7..0282c79 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -207,6 +207,7 @@ static int qCocoaViewCount = 0; composing = false; sendKeyEvents = true; + fromKeyDownEvent = false; [self setHidden:YES]; return self; } @@ -508,7 +509,7 @@ static int qCocoaViewCount = 0; } // Make sure the opengl context is updated on resize. - if (qwidgetprivate && qwidgetprivate->isGLWidget) { + if (qwidgetprivate && qwidgetprivate->isGLWidget && [self window]) { qwidgetprivate->needWindowChange = true; QEvent event(QEvent::MacGLWindowChange); qApp->sendEvent(qwidget, &event); @@ -532,14 +533,26 @@ static int qCocoaViewCount = 0; if (!qwidget) return; + // We use a different graphics system. if (QApplicationPrivate::graphicsSystem() != 0) { - if (qwidgetprivate->maybeBackingStore()) { - // Drawing is handled on the window level - // See qcocoasharedwindowmethods_mac_p.h - if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) - return; + + // Qt handles the painting occuring inside the window. + // Cocoa also keeps track of all widgets as NSView and therefore might + // ask for a repainting of a widget even if Qt is already taking care of it. + // + // The only valid reason for Cocoa to call drawRect: is for window manipulation + // (ie. resize, ...). + // + // Qt will then forward the update to the children. + if (qwidget->isWindow()) { + qwidget->update(qwidget->rect()); + qwidgetprivate->syncBackingStore(qwidget->rect()); } + + // Since we don't want to use the native engine, we must exit. + return; } + CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; CGContextSaveGState(cg); @@ -1203,7 +1216,9 @@ static int qCocoaViewCount = 0; && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) { + fromKeyDownEvent = true; [qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + fromKeyDownEvent = false; } if (sendKeyEvents && !composing) { bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey); @@ -1273,7 +1288,10 @@ static int qCocoaViewCount = 0; }; } - if ([aString length] && composing) { + // When entering characters through Character Viewer or Keyboard Viewer, the text is passed + // through this insertText method. Since we dont receive a keyDown Event in such cases, the + // composing flag will be false. + if (([aString length] && composing) || !fromKeyDownEvent) { // Send the commit string to the widget. composing = false; sendKeyEvents = false; diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index b6b63ca..511423357 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -86,6 +86,7 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; + bool fromKeyDownEvent; QString *composingText; NSInteger dragEnterSequence; } diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 07dbc24..5aa206c 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -156,10 +156,8 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) #ifndef Q_OS_WINCE QLibrary user32Lib(QLatin1String("user32")); - if (user32Lib.load()) { - enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } + enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); if (!enumDisplayMonitors || !getMonitorInfo) { screenCount = GetSystemMetrics(80); // SM_CMONITORS @@ -174,11 +172,9 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) getMonitorInfo = 0; #else QLibrary coreLib(QLatin1String("coredll")); - if (coreLib.load()) { - // CE >= 4.0 case - enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); - } + // CE >= 4.0 case + enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); if ((!enumDisplayMonitors || !getMonitorInfo)) { screenCount = GetSystemMetrics(SM_CMONITORS); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index eade02e..d2b2098 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4392,7 +4392,7 @@ void QGestureEvent::accept(QGesture *gesture) of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}. Clearing the accept flag indicates that the event receiver does not - want the gesture. Unwanted gestures may be propgated to the parent widget. + want the gesture. Unwanted gestures may be propagated to the parent widget. \sa QGestureEvent::accept() */ diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index 377dfe3..6e2ed76 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -129,8 +129,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog"); ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen"); ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo"); diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index c2f275a..562227a 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -76,7 +76,7 @@ static const MacSpecialKey entries[NumEntries] = { { Qt::Key_Backtab, 0x21E4 }, { Qt::Key_Backspace, 0x232B }, { Qt::Key_Return, 0x21B5 }, - { Qt::Key_Enter, 0x21B5 }, + { Qt::Key_Enter, 0x2324 }, { Qt::Key_Delete, 0x2326 }, { Qt::Key_Home, 0x2196 }, { Qt::Key_End, 0x2198 }, @@ -240,7 +240,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V \row \i Preferences \i \i Ctrl+, \i \i \i (none) \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z - \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) + \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none) \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none) \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none) @@ -718,7 +718,6 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac}, {QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All}, {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above {QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All}, {QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac}, {QKeySequence::Forward, 1, Qt::CTRL | Qt::Key_BracketRight, QApplicationPrivate::KB_Mac}, @@ -747,7 +746,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE}, {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac}, {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above + {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above {QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11}, diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 6a91d95..d1a82c2 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -516,9 +516,7 @@ bool QWidgetItem::hasHeightForWidth() const { if (isEmpty()) return false; - if (wid->layout()) - return wid->layout()->hasHeightForWidth(); - return wid->sizePolicy().hasHeightForWidth(); + return wid->d_func()->hasHeightForWidth(); } /*! diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h index d767470..d190d23 100644 --- a/src/gui/kernel/qmacdefines_mac.h +++ b/src/gui/kernel/qmacdefines_mac.h @@ -94,12 +94,6 @@ Yes, it is an informative comment ;-) #include <QtCore/qglobal.h> -#undef OLD_DEBUG -#ifdef DEBUG -# define OLD_DEBUG DEBUG -# undef DEBUG -#endif -#define DEBUG 0 #ifdef qDebug # define old_qDebug qDebug # undef qDebug @@ -179,12 +173,6 @@ typedef AERecord AppleEvent; #undef check #endif -#undef DEBUG -#ifdef OLD_DEBUG -# define DEBUG OLD_DEBUG -# undef OLD_DEBUG -#endif - #ifdef old_qDebug # undef qDebug # define qDebug QT_NO_QDEBUG_MACRO diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 7d23abf..88ff1e6 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -469,7 +469,6 @@ void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec) qt_sendSpontaneousEvent(qApp, &qtabletProximity); } -#ifdef QT_MAC_USE_COCOA // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. struct KeyPair @@ -493,69 +492,107 @@ bool operator<(QChar qchar, const KeyPair &entry) return qchar < entry.cocoaKey; } +bool operator<(const Qt::Key &key, const KeyPair &entry) +{ + return key < entry.qtKey; +} + +bool operator<(const KeyPair &entry, const Qt::Key &key) +{ + return entry.qtKey < key; +} + +static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2) +{ + return entry1.qtKey < entry2.qtKey; +} + +static const int NumEntries = 59; +static const KeyPair entries[NumEntries] = { + { NSEnterCharacter, Qt::Key_Enter }, + { NSBackspaceCharacter, Qt::Key_Backspace }, + { NSTabCharacter, Qt::Key_Tab }, + { NSNewlineCharacter, Qt::Key_Return }, + { NSCarriageReturnCharacter, Qt::Key_Return }, + { NSBackTabCharacter, Qt::Key_Backtab }, + { NSDeleteCharacter, Qt::Key_Delete }, + { kEscapeCharCode, Qt::Key_Escape }, + { NSUpArrowFunctionKey, Qt::Key_Up }, + { NSDownArrowFunctionKey, Qt::Key_Down }, + { NSLeftArrowFunctionKey, Qt::Key_Left }, + { NSRightArrowFunctionKey, Qt::Key_Right }, + { NSF1FunctionKey, Qt::Key_F1 }, + { NSF2FunctionKey, Qt::Key_F2 }, + { NSF3FunctionKey, Qt::Key_F3 }, + { NSF4FunctionKey, Qt::Key_F4 }, + { NSF5FunctionKey, Qt::Key_F5 }, + { NSF6FunctionKey, Qt::Key_F6 }, + { NSF7FunctionKey, Qt::Key_F7 }, + { NSF8FunctionKey, Qt::Key_F8 }, + { NSF9FunctionKey, Qt::Key_F8 }, + { NSF10FunctionKey, Qt::Key_F10 }, + { NSF11FunctionKey, Qt::Key_F11 }, + { NSF12FunctionKey, Qt::Key_F12 }, + { NSF13FunctionKey, Qt::Key_F13 }, + { NSF14FunctionKey, Qt::Key_F14 }, + { NSF15FunctionKey, Qt::Key_F15 }, + { NSF16FunctionKey, Qt::Key_F16 }, + { NSF17FunctionKey, Qt::Key_F17 }, + { NSF18FunctionKey, Qt::Key_F18 }, + { NSF19FunctionKey, Qt::Key_F19 }, + { NSF20FunctionKey, Qt::Key_F20 }, + { NSF21FunctionKey, Qt::Key_F21 }, + { NSF22FunctionKey, Qt::Key_F22 }, + { NSF23FunctionKey, Qt::Key_F23 }, + { NSF24FunctionKey, Qt::Key_F24 }, + { NSF25FunctionKey, Qt::Key_F25 }, + { NSF26FunctionKey, Qt::Key_F26 }, + { NSF27FunctionKey, Qt::Key_F27 }, + { NSF28FunctionKey, Qt::Key_F28 }, + { NSF29FunctionKey, Qt::Key_F29 }, + { NSF30FunctionKey, Qt::Key_F30 }, + { NSF31FunctionKey, Qt::Key_F31 }, + { NSF32FunctionKey, Qt::Key_F32 }, + { NSF33FunctionKey, Qt::Key_F33 }, + { NSF34FunctionKey, Qt::Key_F34 }, + { NSF35FunctionKey, Qt::Key_F35 }, + { NSInsertFunctionKey, Qt::Key_Insert }, + { NSDeleteFunctionKey, Qt::Key_Delete }, + { NSHomeFunctionKey, Qt::Key_Home }, + { NSEndFunctionKey, Qt::Key_End }, + { NSPageUpFunctionKey, Qt::Key_PageUp }, + { NSPageDownFunctionKey, Qt::Key_PageDown }, + { NSPrintScreenFunctionKey, Qt::Key_Print }, + { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, + { NSPauseFunctionKey, Qt::Key_Pause }, + { NSSysReqFunctionKey, Qt::Key_SysReq }, + { NSMenuFunctionKey, Qt::Key_Menu }, + { NSHelpFunctionKey, Qt::Key_Help }, +}; +static const KeyPair * const end = entries + NumEntries; + +QChar qtKey2CocoaKey(Qt::Key key) +{ + // The first time this function is called, create a reverse + // looup table sorted on Qt Key rather than Cocoa key: + static QVector<KeyPair> rev_entries(NumEntries); + static bool mustInit = true; + if (mustInit){ + mustInit = false; + for (int i=0; i<NumEntries; ++i) + rev_entries[i] = entries[i]; + qSort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan); + } + const QVector<KeyPair>::iterator i + = qBinaryFind(rev_entries.begin(), rev_entries.end(), key); + if (i == rev_entries.end()) + return QChar(); + return i->cocoaKey; +} + +#ifdef QT_MAC_USE_COCOA static Qt::Key cocoaKey2QtKey(QChar keyCode) { - static const int NumEntries = 57; - static const KeyPair entries[NumEntries] = { - { NSEnterCharacter, Qt::Key_Enter }, - { NSTabCharacter, Qt::Key_Tab }, - { NSCarriageReturnCharacter, Qt::Key_Return }, - { NSBackTabCharacter, Qt::Key_Backtab }, - { kEscapeCharCode, Qt::Key_Escape }, - { NSDeleteCharacter, Qt::Key_Backspace }, - { NSUpArrowFunctionKey, Qt::Key_Up }, - { NSDownArrowFunctionKey, Qt::Key_Down }, - { NSLeftArrowFunctionKey, Qt::Key_Left }, - { NSRightArrowFunctionKey, Qt::Key_Right }, - { NSF1FunctionKey, Qt::Key_F1 }, - { NSF2FunctionKey, Qt::Key_F2 }, - { NSF3FunctionKey, Qt::Key_F3 }, - { NSF4FunctionKey, Qt::Key_F4 }, - { NSF5FunctionKey, Qt::Key_F5 }, - { NSF6FunctionKey, Qt::Key_F6 }, - { NSF7FunctionKey, Qt::Key_F7 }, - { NSF8FunctionKey, Qt::Key_F8 }, - { NSF9FunctionKey, Qt::Key_F8 }, - { NSF10FunctionKey, Qt::Key_F10 }, - { NSF11FunctionKey, Qt::Key_F11 }, - { NSF12FunctionKey, Qt::Key_F12 }, - { NSF13FunctionKey, Qt::Key_F13 }, - { NSF14FunctionKey, Qt::Key_F14 }, - { NSF15FunctionKey, Qt::Key_F15 }, - { NSF16FunctionKey, Qt::Key_F16 }, - { NSF17FunctionKey, Qt::Key_F17 }, - { NSF18FunctionKey, Qt::Key_F18 }, - { NSF19FunctionKey, Qt::Key_F19 }, - { NSF20FunctionKey, Qt::Key_F20 }, - { NSF21FunctionKey, Qt::Key_F21 }, - { NSF22FunctionKey, Qt::Key_F22 }, - { NSF23FunctionKey, Qt::Key_F23 }, - { NSF24FunctionKey, Qt::Key_F24 }, - { NSF25FunctionKey, Qt::Key_F25 }, - { NSF26FunctionKey, Qt::Key_F26 }, - { NSF27FunctionKey, Qt::Key_F27 }, - { NSF28FunctionKey, Qt::Key_F28 }, - { NSF29FunctionKey, Qt::Key_F29 }, - { NSF30FunctionKey, Qt::Key_F30 }, - { NSF31FunctionKey, Qt::Key_F31 }, - { NSF32FunctionKey, Qt::Key_F32 }, - { NSF33FunctionKey, Qt::Key_F33 }, - { NSF34FunctionKey, Qt::Key_F34 }, - { NSF35FunctionKey, Qt::Key_F35 }, - { NSInsertFunctionKey, Qt::Key_Insert }, - { NSDeleteFunctionKey, Qt::Key_Delete }, - { NSHomeFunctionKey, Qt::Key_Home }, - { NSEndFunctionKey, Qt::Key_End }, - { NSPageUpFunctionKey, Qt::Key_PageUp }, - { NSPageDownFunctionKey, Qt::Key_PageDown }, - { NSPrintScreenFunctionKey, Qt::Key_Print }, - { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, - { NSPauseFunctionKey, Qt::Key_Pause }, - { NSSysReqFunctionKey, Qt::Key_SysReq }, - { NSMenuFunctionKey, Qt::Key_Menu }, - { NSHelpFunctionKey, Qt::Key_Help }, - }; - static const KeyPair * const end = entries + NumEntries; const KeyPair *i = qBinaryFind(entries, end, keyCode); if (i == end) return Qt::Key(keyCode.unicode()); @@ -1204,7 +1241,7 @@ void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widge // We have the original method here. Proceed and swap the methods. method_exchangeImplementations(m1, m0); widget->originalDrawMethod = false; - [window display]; + [theWindow display]; } } @@ -1227,7 +1264,7 @@ void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivat } method_exchangeImplementations(m1, m0); widget->originalDrawMethod = true; - [window display]; + [theWindow display]; } #endif // QT_MAC_USE_COCOA @@ -1297,7 +1334,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else - CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]); + CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort]; #endif return context; } @@ -1426,39 +1463,17 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor) [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; } -// WARNING: If Qt did not create NSApplication (e.g. in case it is -// used as a plugin), and at the same time, there is no window on -// screen (or the window that the event is sendt to becomes hidden etc -// before the event gets delivered), the message will not be performed. -bool qt_cocoaPostMessage(id target, SEL selector) +void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2) { - if (!target) - return false; - - NSInteger windowNumber = 0; - if (![NSApp isMemberOfClass:[QNSApplication class]]) { - // INVARIANT: Cocoa is not using our NSApplication subclass. That means - // we don't control the main event handler either. So target the event - // for one of the windows on screen: - NSWindow *nswin = [NSApp mainWindow]; - if (!nswin) { - nswin = [NSApp keyWindow]; - if (!nswin) - return false; - } - windowNumber = [nswin windowNumber]; - } - - // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! // That is why we need to split the address in two parts: - QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector); + QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector, argCount, arg1, arg2); quint32 lower = quintptr(args); quint32 upper = quintptr(args) >> 32; NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber + location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; [NSApp postEvent:e atStart:NO]; - return true; } #endif @@ -1497,7 +1512,7 @@ void macDrawRectOnTop(void * /*OSWindowRef */window) NSRect contentRect = [contentView frame]; // Draw a line on top of the already drawn line. // We need to check if we are active or not to use the proper color. - if([window isKeyWindow] || [window isMainWindow]) { + if([theWindow isKeyWindow] || [theWindow isMainWindow]) { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; @@ -1517,7 +1532,7 @@ void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) { OSWindowRef theWindow = static_cast<OSWindowRef>(window); NSApplication *application = [NSApplication sharedApplication]; - NSToolbar *toolbar = [window toolbar]; + NSToolbar *toolbar = [theWindow toolbar]; if([application isActive]) { // Launched from finder [toolbar setShowsBaselineSeparator:NO]; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index c6c2db2..5c23392 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -202,17 +202,25 @@ class QCocoaPostMessageArgs { public: id target; SEL selector; - QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector) + int argCount; + id arg1; + id arg2; + QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0) + : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2) { [target retain]; + [arg1 retain]; + [arg2 retain]; } ~QCocoaPostMessageArgs() { + [arg2 release]; + [arg1 release]; [target release]; } }; -bool qt_cocoaPostMessage(id target, SEL selector); +void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0); #endif #endif diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index c8fcf45..88fdbc6 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -353,7 +353,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #ifndef QT_NO_STYLE_STYLESHEET if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) { //the stylesheet need to know the real parent - QTipLabel::instance->setProperty("_q_stylesheet_parent", qVariantFromValue(w)); + QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w)); //we force the style to be the QStyleSheetStyle, and force to clear the cache as well. QTipLabel::instance->setStyleSheet(QLatin1String("/* */")); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 3d2bfe2..0baecce 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1580,7 +1580,8 @@ QWidget::~QWidget() d->needsFlush = 0; // set all QPointers for this object to zero - QObjectPrivate::clearGuards(this); + if (d->hasGuards) + QObjectPrivate::clearGuards(this); if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); @@ -1808,13 +1809,7 @@ void QWidgetPrivate::syncBackingStore() repaint_sys(dirty); dirty = QRegion(); } else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), QRegion()); -#else bs->sync(); -#endif } } @@ -1823,13 +1818,7 @@ void QWidgetPrivate::syncBackingStore(const QRegion ®ion) if (paintOnScreen()) repaint_sys(region); else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), region); -#else bs->sync(q_func(), region); -#endif } } @@ -6576,7 +6565,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) // that can take keyboard focus so that second is inserted after // that last child, and the focus order within first is (more // likely to be) preserved. - QList<QWidget *> l = qFindChildren<QWidget *>(first); + QList<QWidget *> l = first->findChildren<QWidget *>(); for (int i = l.size()-1; i >= 0; --i) { QWidget * next = l.at(i); if (next->window() == fp->window()) { @@ -9736,6 +9725,23 @@ int QWidget::heightForWidth(int w) const return -1; } + +/*! + \internal + + *virtual private* + + This is a bit hackish, but ideally we would have created a virtual function + in the public API (however, too late...) so that subclasses could reimplement + their own function. + Instead we add a virtual function to QWidgetPrivate. + ### Qt5: move to public class and make virtual +*/ +bool QWidgetPrivate::hasHeightForWidth() const +{ + return layout ? layout->hasHeightForWidth() : size_policy.hasHeightForWidth(); +} + /*! \fn QWidget *QWidget::childAt(int x, int y) const diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 941bd68..980f40f 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -898,13 +898,6 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags) -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template <> inline QWidget *qobject_cast_helper<QWidget*>(QObject *o, QWidget *) -{ - if (!o || !o->isWidgetType()) return 0; - return (QWidget*)(o); -} -#else template <> inline QWidget *qobject_cast<QWidget*>(QObject *o) { if (!o || !o->isWidgetType()) return 0; @@ -915,7 +908,6 @@ template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o) if (!o || !o->isWidgetType()) return 0; return static_cast<const QWidget*>(o); } -#endif inline QWidget *QWidget::childAt(int ax, int ay) const { return childAt(QPoint(ax, ay)); } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1979c84..ef7e1d3 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -223,6 +223,8 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) for (NSWindow *window in windows) { NSArray *drawers = [window drawers]; for (NSDrawer *drawer in drawers) { + if ([drawer contentView] == widgetView) + return drawer; NSArray *views = [[drawer contentView] subviews]; for (NSView *view in views) { if (view == widgetView) @@ -237,6 +239,9 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) static void qt_mac_destructView(OSViewRef view) { #ifdef QT_MAC_USE_COCOA + NSWindow *window = [view window]; + if ([window contentView] == view) + [window setContentView:[[NSView alloc] initWithFrame:[view bounds]]]; [view removeFromSuperview]; [view release]; #else @@ -2291,28 +2296,23 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin Q_UNUSED(dialog); data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty + OSViewRef nsview = (OSViewRef)data.winid; - OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef); if (!nsview) { - nsview = qt_mac_create_widget(q, this, window_contentview); + nsview = qt_mac_create_widget(q, this, 0); setWinId(WId(nsview)); - } else { - [window_contentview addSubview:nsview]; - } - if (nsview) { - NSRect bounds = [window_contentview bounds]; - [nsview setFrame:bounds]; - [nsview setHidden:NO]; - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - transferChildren(); - - // Tell Cocoa explicit that we wan't the view to receive key events - // (regardless of focus policy) because this is how it works on other - // platforms (and in the carbon port): - if (!qApp->focusWidget()) - [windowRef makeFirstResponder:nsview]; } + [windowRef setContentView:nsview]; + [nsview setHidden:NO]; + if (q->testAttribute(Qt::WA_DropSiteRegistered)) + registerDropSite(true); + transferChildren(); + + // Tell Cocoa explicit that we wan't the view to receive key events + // (regardless of focus policy) because this is how it works on other + // platforms (and in the carbon port): + if (!qApp->focusWidget()) + [windowRef makeFirstResponder:nsview]; if (topExtra->posFromMove) { updateFrameStrut(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 4a79dc7..c943bd8 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -542,6 +542,7 @@ public: bool setMinimumSize_helper(int &minw, int &minh); bool setMaximumSize_helper(int &maxw, int &maxh); + virtual bool hasHeightForWidth() const; void setConstraints_sys(); bool pointInsideRectAndMask(const QPoint &) const; QWidget *childAt_helper(const QPoint &, bool) const; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 7494f92..222d707 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -360,7 +360,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen)) data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY)); - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(true, desktop)); control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); @@ -405,7 +407,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(!parentWidget)); // Symbian windows are always created in an inactive state diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 59035b1..05d9a5f 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1635,8 +1635,6 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } -extern Q_GUI_EXPORT HDC qt_win_display_dc(); - int QWidget::metric(PaintDeviceMetric m) const { Q_D(const QWidget); @@ -1646,7 +1644,7 @@ int QWidget::metric(PaintDeviceMetric m) const } else if (m == PdmHeight) { val = data->crect.height(); } else { - HDC gdc = qt_win_display_dc(); + HDC gdc = GetDC(0); switch (m) { case PdmDpiX: case PdmPhysicalDpiX: @@ -1697,6 +1695,7 @@ int QWidget::metric(PaintDeviceMetric m) const val = 0; qWarning("QWidget::metric: Invalid metric command"); } + ReleaseDC(0, gdc); } return val; } diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 16c7f97..2f03bd0 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -102,8 +102,6 @@ QMatrix4x4::QMatrix4x4(const qreal *values) \sa optimize() */ -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) - /*! \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) @@ -112,7 +110,7 @@ QMatrix4x4::QMatrix4x4(const qreal *values) the remaining elements are filled with elements from the identity matrix. - \sa toGenericMatrix(), qGenericMatrixToMatrix4x4() + \sa toGenericMatrix() */ /*! @@ -122,34 +120,32 @@ QMatrix4x4::QMatrix4x4(const qreal *values) top-most M rows of this 4x4 matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - - \sa qGenericMatrixFromMatrix4x4() */ -#endif - /*! \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) \relates QMatrix4x4 + \obsolete Returns a 4x4 matrix constructed from the left-most 4 columns and top-most 4 rows of \a matrix. If \a matrix has less than 4 columns or rows, the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixFromMatrix4x4() + \sa QMatrix4x4(const QGenericMatrix &) */ /*! \fn QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) \relates QMatrix4x4 + \obsolete Returns a NxM generic matrix constructed from the left-most N columns and top-most M rows of \a matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix() + \sa QMatrix4x4::toGenericMatrix() */ /*! diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 0671fa8..598058c 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -69,10 +69,10 @@ public: qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44); -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) + template <int N, int M> explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix); -#endif + QMatrix4x4(const qreal *values, int cols, int rows); QMatrix4x4(const QTransform& transform); QMatrix4x4(const QMatrix& matrix); @@ -169,10 +169,8 @@ public: QRect mapRect(const QRect& rect) const; QRectF mapRect(const QRectF& rect) const; -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) template <int N, int M> QGenericMatrix<N, M, qreal> toGenericMatrix() const; -#endif inline qreal *data(); inline const qreal *data() const { return m[0]; } @@ -223,8 +221,6 @@ inline QMatrix4x4::QMatrix4x4 flagBits = General; } -#if !defined(QT_NO_MEMBER_TEMPLATES) - template <int N, int M> Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4 (const QGenericMatrix<N, M, qreal>& matrix) @@ -261,8 +257,6 @@ QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const return result; } -#endif - inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const { Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); @@ -992,14 +986,15 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &); #endif +#ifdef QT_DEPRECATED template <int N, int M> -QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) +QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) { return QMatrix4x4(matrix.constData(), N, M); } template <int N, int M> -QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) +QT_DEPRECATED QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) { QGenericMatrix<N, M, qreal> result; const qreal *m = matrix.constData(); @@ -1016,6 +1011,7 @@ QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix } return result; } +#endif #endif diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 276da93..d6beb72 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -656,6 +656,46 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const return buffer; } +/** \internal + interpolate 4 argb pixels with the distx and disty factor. + distx and disty bust be between 0 and 16 + */ +static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty, int idistx, int idisty) +{ + uint tlrb = ((tl & 0x00ff00ff) * idistx * idisty); + uint tlag = (((tl & 0xff00ff00) >> 8) * idistx * idisty); + uint trrb = ((tr & 0x00ff00ff) * distx * idisty); + uint trag = (((tr & 0xff00ff00) >> 8) * distx * idisty); + uint blrb = ((bl & 0x00ff00ff) * idistx * disty); + uint blag = (((bl & 0xff00ff00) >> 8) * idistx * disty); + uint brrb = ((br & 0x00ff00ff) * distx * disty); + uint brag = (((br & 0xff00ff00) >> 8) * distx * disty); + return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00); +} + + +template<TextureBlendType blendType> +Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) +{ + if (blendType == BlendTransformedBilinearTiled) { + v1 %= max; + if (v1 < 0) v1 += max; + v2 = v1 + 1; + v2 %= max; + } else { + if (v1 < l1) { + v2 = v1 = l1; + } else if (v1 >= l2 - 1) { + v2 = v1 = l2 - 1; + } else { + v2 = v1 + 1; + } + } + + Q_ASSERT(v1 >= 0 && v1 < max); + Q_ASSERT(v2 >= 0 && v2 < max); +} + template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, @@ -696,64 +736,229 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fx -= half_point; fy -= half_point; - while (b < end) { - int x1 = (fx >> 16); - int x2; + + if (fdy == 0) { //simple scale, no rotation int y1 = (fy >> 16); int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; + if (fdx <= fixed_scale && fdx > 0) { // scale up on X + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + int count = length * data->m11 + 2; + int x = fx >> 16; + + // The idea is first to do the interpolation between the row s1 and the row s2 + // into an intermediate buffer, then we interpolate between two pixel of this buffer. + + // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB + // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG + quint32 intermediate_buffer[2][buffer_size + 2]; + Q_ASSERT(length * data->m11 <= buffer_size); + int f = 0; + int lim = count; + if (blendType == BlendTransformedBilinearTiled) { + x %= image_width; + if (x < 0) x += image_width; } else { - x2 = x1 + 1; + lim = qMin(count, image_x2-x); + if (x < image_x1) { + Q_ASSERT(x < image_x2); + uint t = fetch(s1, image_x1, data->texture.colorTable); + uint b = fetch(s2, image_x1, data->texture.colorTable); + quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + do { + intermediate_buffer[0][f] = rb; + intermediate_buffer[1][f] = ag; + f++; + x++; + } while (x < image_x1 && f < lim); + } } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; + +#if defined(QT_ALWAYS_HAVE_SSE2) + if (blendType != BlendTransformedBilinearTiled && + (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { + + const __m128i disty_ = _mm_set1_epi16(disty); + const __m128i idisty_ = _mm_set1_epi16(idisty); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + lim -= 3; + for (; f < lim; x += 4, f += 4) { + // Load 4 pixels from s1, and split the alpha-green and red-blue component + __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x)); + __m128i topAG = _mm_srli_epi16(top, 8); + __m128i topRB = _mm_and_si128(top, colorMask); + // Multiplies each colour component by idisty + topAG = _mm_mullo_epi16 (topAG, idisty_); + topRB = _mm_mullo_epi16 (topRB, idisty_); + + // Same for the s2 vector + __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x)); + __m128i bottomAG = _mm_srli_epi16(bottom, 8); + __m128i bottomRB = _mm_and_si128(bottom, colorMask); + bottomAG = _mm_mullo_epi16 (bottomAG, disty_); + bottomRB = _mm_mullo_epi16 (bottomRB, disty_); + + // Add the values, and shift to only keep 8 significant bits per colors + __m128i rAG =_mm_add_epi16(topAG, bottomAG); + rAG = _mm_srli_epi16(rAG, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); + __m128i rRB =_mm_add_epi16(topRB, bottomRB); + rRB = _mm_srli_epi16(rRB, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); + } + } +#endif + for (; f < count; f++) { // Same as above but without sse2 + if (blendType == BlendTransformedBilinearTiled) { + if (x >= image_width) x -= image_width; + } else { + x = qMin(x, image_x2 - 1); + } + + uint t = fetch(s1, x, data->texture.colorTable); + uint b = fetch(s2, x, data->texture.colorTable); + + intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + x++; + } + // Now interpolate the values from the intermediate_buffer to get the final result. + fx &= fixed_scale - 1; + Q_ASSERT((fx >> 16) == 0); + while (b < end) { + register int x1 = (fx >> 16); + register int x2 = x1 + 1; + Q_ASSERT(x1 >= 0); + Q_ASSERT(x2 < count); + + register int distx = (fx & 0x0000ffff) >> 8; + register int idistx = 256 - distx; + int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; + int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; + *b = rb | ag; + b++; + fx += fdx; + } + } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 8; + int idistx = 256 - distx; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + + fx += fdx; + ++b; + } + } else { //scale down + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 12; + int idisty = 16 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + int distx = (fx & 0x0000ffff) >> 12; + int idistx = 16 - distx; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + fx += fdx; + ++b; } } + } else { //rotation + if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { + //if we are zooming more than 8 times, we use 8bit precision for the position. + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int idisty = 256 - disty; + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + int idistx = 256 - distx; + int idisty = 256 - disty; - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - fx += fdx; - fy += fdy; - ++b; + fx += fdx; + fy += fdy; + ++b; + } + } else { + //we are zooming less than 8x, use 4bit precision + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 12; + int disty = (fy & 0x0000ffff) >> 12; + int idistx = 16 - distx; + int idisty = 16 - disty; + + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + + fx += fdx; + fy += fdy; + ++b; + } + } } } else { const qreal fdx = data->m11; @@ -779,37 +984,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int idistx = 256 - distx; int idisty = 256 - disty; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < 0) { - x2 = x1 = 0; - } else if (x1 >= image_width - 1) { - x2 = x1 = image_width - 1; - } else { - x2 = x1 + 1; - } - if (y1 < 0) { - y2 = y1 = 0; - } else if (y1 >= image_height - 1) { - y2 = y1 = image_height - 1; - } else { - y2 = y1 + 1; - } - } - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -5216,37 +5392,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const int y1 = (y >> 16); int y2; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); int y1_offset = y1 * scanline_offset; int y2_offset = y2 * scanline_offset; @@ -5326,37 +5473,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const int idistx = 256 - distx; int idisty = 256 - disty; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); int y1_offset = y1 * scanline_offset; int y2_offset = y2 * scanline_offset; diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index bf03545..72e5833 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #define qreal_to_fixed_26_6(f) (int(f * 64)) @@ -216,13 +214,6 @@ void QOutlineMapper::endOutline() elements = m_elements_dev.data(); } - if (m_round_coords) { - // round coordinates to match outlines drawn with drawLine_midpoint_i - for (int i = 0; i < m_elements.size(); ++i) - elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta), - qFloor(elements[i].y() + aliasedCoordinateDelta)); - } - controlPointRect = boundingRect(elements, element_count); #ifdef QT_DEBUG_CONVERT diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h index d534f76..fcfc9bf 100644 --- a/src/gui/painting/qoutlinemapper_p.h +++ b/src/gui/painting/qoutlinemapper_p.h @@ -95,8 +95,7 @@ public: m_tags(0), m_contours(0), m_polygon_dev(0), - m_in_clip_elements(false), - m_round_coords(false) + m_in_clip_elements(false) { } @@ -202,8 +201,6 @@ public: QT_FT_Outline *convertPath(const QPainterPath &path); QT_FT_Outline *convertPath(const QVectorPath &path); - void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; } - inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); } public: @@ -237,9 +234,6 @@ public: bool m_valid; bool m_in_clip_elements; - -private: - bool m_round_coords; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 3a4c94c..d4a8213 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -130,7 +130,7 @@ QPaintBufferPrivate::~QPaintBufferPrivate() for (int i = 0; i < commands.size(); ++i) { const QPaintBufferCommand &cmd = commands.at(i); if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem) - delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset))); + delete reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(variants.at(cmd.offset))); } } @@ -330,7 +330,7 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetBrush: " << brush; break; } @@ -354,27 +354,27 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << pen; break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << brush; break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; break; } @@ -451,12 +451,12 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetPen: " << pen; break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetTransform, offset: " << cmd.offset << xform; break; } @@ -532,7 +532,7 @@ QString QPaintBuffer::commandDescription(int command) const case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d_ptr->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1287,7 +1287,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti) qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text(); #endif if (m_stream_raw_text_items) { - QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti))); + QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, QVariant::fromValue<void *>(new QTextItemIntCopy(ti))); QFont font(ti.font()); font.setUnderline(false); @@ -1429,7 +1429,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetPen: " << pen; #endif @@ -1437,7 +1437,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetBrush: " << brush; #endif @@ -1452,7 +1452,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform; #endif @@ -1520,7 +1520,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1531,7 +1531,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1705,7 +1705,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1714,7 +1714,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; @@ -1790,7 +1790,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1885,7 +1885,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1896,7 +1896,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1907,7 +1907,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1916,7 +1916,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 09a87aa..0b76898 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -123,9 +123,6 @@ void dumpClip(int width, int height, const QClipData *clip); // 4 pixels. #define int_dim(pos, dim) (int(pos+dim) - int(pos)) -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #ifdef Q_WS_WIN extern bool qt_cleartype_enabled; #endif @@ -1753,10 +1750,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - int x1 = qRound(rect.x() + aliasedCoordinateDelta); - int y1 = qRound(rect.y() + aliasedCoordinateDelta); - int x2 = qRound(rect.right() + aliasedCoordinateDelta); - int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + int x1 = qRound(rect.x()); + int y1 = qRound(rect.y()); + int x2 = qRound(rect.right()); + int y2 = qRound(rect.bottom()); if (x2 < x1) qSwap(x1, x2); @@ -2025,7 +2022,6 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly */ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) { - Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); #ifdef QT_DEBUG_DRAW @@ -2046,9 +2042,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly if (mode != PolylineMode) { // Do the fill... if (s->brushData.blend) { - d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque()); fillPolygon(points, pointCount, mode); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2100,7 +2094,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg if (s->brushData.blend) { // Compose polygon fill.., ensureOutlineMapper(); - d->outlineMapper->setCoordinateRounding(s->penData.blend != 0); d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); d->outlineMapper->moveTo(*points); const QPoint *p = points; @@ -2114,7 +2107,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &s->brushData); d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data()); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2162,13 +2154,11 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC : LineDrawNormal); int dashOffset = int(s->lastPen.dashOffset()); - const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta); - // Draw all the line segments. for (int i=1; i<pointCount; ++i) { - QPointF lp1 = points[i-1] * s->matrix + offs; - QPointF lp2 = points[i] * s->matrix + offs; + QPointF lp1 = points[i-1] * s->matrix; + QPointF lp2 = points[i] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2190,8 +2180,8 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC // Polygons are implicitly closed. if (needs_closing) { - QPointF lp1 = points[pointCount-1] * s->matrix + offs; - QPointF lp2 = points[0] * s->matrix + offs; + QPointF lp1 = points[pointCount-1] * s->matrix; + QPointF lp2 = points[0] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2579,10 +2569,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe int sr_b = qCeil(sr.bottom()) - 1; if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { - // as fillRect will apply the aliased coordinate delta we need to - // subtract it here as we don't use it for image drawing QTransform old = s->matrix; - s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. QRgb color = img.pixel(sr_l, sr_t); @@ -2726,11 +2713,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe d->initializeRasterizer(&d->image_filler_xform); d->rasterizer->setAntialiased(s->flags.antialiased); - const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta); - const QRectF &rect = r.normalized(); - const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs; - const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs; + const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); + const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f); if (s->flags.tx_noshear) d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width()); @@ -2739,13 +2724,12 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe return; } #endif - const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta; QPainterPath path; path.addRect(r); QTransform m = s->matrix; s->matrix = QTransform(m.m11(), m.m12(), m.m13(), m.m21(), m.m22(), m.m23(), - m.m31() - offs, m.m32() - offs, m.m33()); + m.m31(), m.m32(), m.m33()); fillPath(path, &d->image_filler_xform); s->matrix = m; } else { @@ -3099,6 +3083,7 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, } cache->populate(fontEngine, numGlyphs, glyphs, positions); + cache->fillInPendingGlyphs(); const QImage &image = cache->image(); int bpl = image.bytesPerLine(); @@ -3113,13 +3098,11 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, int margin = cache->glyphMargin(); - const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); - const uchar *bits = image.bits(); for (int i=0; i<numGlyphs; ++i) { const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); - int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; - int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; + int x = qFloor(positions[i].x) + c.baseLineX - margin; + int y = qFloor(positions[i].y) - c.baseLineY - margin; // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", // c.x, c.y, @@ -3157,16 +3140,14 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti) fe->setFontScale(matrix.m11()); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta); - for (int i=0; i<glyphs.size(); ++i) { TOpenFontCharMetrics tmetrics; const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize); const glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); - const int x = qFloor(positions[i].x + metrics.x + aliasDelta); - const int y = qFloor(positions[i].y + metrics.y + aliasDelta); + const int x = qFloor(positions[i].x + metrics.x); + const int y = qFloor(positions[i].y + metrics.y); alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); } @@ -3380,7 +3361,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte #if defined(Q_WS_QWS) if (fontEngine->type() == QFontEngine::Box) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } @@ -3389,7 +3370,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte || (fontEngine->type() == QFontEngine::Proxy && !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline())) )) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } #endif // Q_WS_QWS @@ -3450,7 +3431,6 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } - QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); FT_Face lockedFace = 0; int depth; @@ -3498,8 +3478,8 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte }; alphaPenBlt(glyph->data, pitch, depth, - qFloor(positions[i].x + offs) + glyph->x, - qFloor(positions[i].y + offs) - glyph->y, + qFloor(positions[i].x) + glyph->x, + qFloor(positions[i].y) - glyph->y, glyph->width, glyph->height); } if (lockedFace) @@ -3636,8 +3616,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m11 = int(s->matrix.m11()); int m22 = int(s->matrix.m22()); - int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); - int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); + int dx = qFloor(s->matrix.dx()); + int dy = qFloor(s->matrix.dy()); for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { @@ -3741,7 +3721,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); - QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); + QLineF line = lines[i] * s->matrix; const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index be90006..1f1bb29 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -61,6 +61,8 @@ #include "qstyle.h" #include "qthread.h" #include "qvarlengtharray.h" +#include "qstatictext.h" +#include "qglyphs.h" #include <private/qfontengine_p.h> #include <private/qpaintengine_p.h> @@ -70,8 +72,8 @@ #include <private/qwidget_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qmath_p.h> -#include <qstatictext.h> #include <private/qstatictext_p.h> +#include <private/qglyphs_p.h> #include <private/qstylehelper_p.h> QT_BEGIN_NAMESPACE @@ -92,7 +94,7 @@ void qt_format_text(const QFont &font, QPainter *painter); static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, @@ -162,6 +164,10 @@ static bool qt_painter_thread_test(int devType, const char *what, bool extraCond #endif break; default: +#ifdef Q_WS_X11 + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + return true; +#endif if (!extraCondition && QThread::currentThread() != qApp->thread()) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; @@ -2701,6 +2707,61 @@ QPainterPath QPainter::clipPath() const } /*! + Returns the bounding rectangle of the current clip if there is a clip; + otherwise returns an empty rectangle. Note that the clip region is + given in logical coordinates. + + The bounding rectangle is not guaranteed to be tight. + + \sa setClipRect(), setClipPath(), setClipRegion() + + \since 4.8 + */ + +QRectF QPainter::clipBoundingRect() const +{ + Q_D(const QPainter); + + if (!d->engine) { + qWarning("QPainter::clipBoundingRect: Painter not active"); + return QRectF(); + } + + // Accumulate the bounding box in device space. This is not 100% + // precise, but it fits within the guarantee and it is resonably + // fast. + QRectF bounds; + for (int i=0; i<d->state->clipInfo.size(); ++i) { + QRectF r; + const QPainterClipInfo &info = d->state->clipInfo.at(i); + + if (info.clipType == QPainterClipInfo::RectClip) + r = info.rect; + else if (info.clipType == QPainterClipInfo::RegionClip) + r = info.region.boundingRect(); + else + r = info.path.boundingRect(); + + r = info.matrix.mapRect(r); + + if (i == 0) + bounds = r; + else if (info.operation == Qt::IntersectClip) + bounds &= r; + else if (info.operation == Qt::UniteClip) + bounds |= r; + } + + + // Map the rectangle back into logical space using the inverse + // matrix. + if (!d->txinv) + const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); + + return d->invMatrix.mapRect(bounds); +} + +/*! \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation) Enables clipping, and sets the clip region to the given \a @@ -5256,7 +5317,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif if (d->extended) { @@ -5326,7 +5387,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) if (!d->engine || pm.isNull()) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif qreal x = r.x(); @@ -5711,17 +5772,50 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); } +/*! + Draws the glyphs represented by \a glyphs at \a position. The \a position gives the + edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font + selected on \a glyphs and at offsets given by the positions in \a glyphs. + + \since 4.8 + + \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes() +*/ +void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs) +{ + Q_D(QPainter); + + QFont oldFont = d->state->font; + d->state->font = glyphs.font(); + + QVector<quint32> glyphIndexes = glyphs.glyphIndexes(); + QVector<QPointF> glyphPositions = glyphs.positions(); + + int count = qMin(glyphIndexes.size(), glyphPositions.size()); + QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count); + for (int i=0; i<count; ++i) + fixedPointPositions[i] = QFixedPoint::fromPointF(position + glyphPositions.at(i)); + + d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count); + + d->state->font = oldFont; +} void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray, int glyphCount) { + QVarLengthArray<QFixedPoint, 128> positions(glyphCount); + for (int i=0; i<glyphCount; ++i) + positions[i] = QFixedPoint::fromPointF(positionArray[i]); + QPainterPrivate *painter_d = QPainterPrivate::get(painter); - painter_d->drawGlyphs(glyphArray, positionArray, glyphCount); + painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, - int glyphCount) +void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount) { + Q_Q(QPainter); + updateState(state); QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common); @@ -5736,12 +5830,27 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); } - QVarLengthArray<QFixedPoint, 128> positions; + QFixed leftMost; + QFixed rightMost; + QFixed baseLine; for (int i=0; i<glyphCount; ++i) { - QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]); - positions.append(fp); + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); + if (i == 0 || leftMost > positions[i].x) + leftMost = positions[i].x; + + // We don't support glyphs that do not share a common baseline. If this turns out to + // be a relevant use case, then we need to find clusters of glyphs that share a baseline + // and do a drawTextItemDecorations call per cluster. + if (i == 0 || baseLine < positions[i].y) + baseLine = positions[i].y; + + // We use the advance rather than the actual bounds to match the algorithm in drawText() + if (i == 0 || rightMost < positions[i].x + gm.xoff) + rightMost = positions[i].x + gm.xoff; } + QFixed width = rightMost - leftMost; + if (extended != 0) { QStaticTextItem staticTextItem; staticTextItem.color = state->pen.color(); @@ -5749,7 +5858,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit staticTextItem.fontEngine = fontEngine; staticTextItem.numGlyphs = glyphCount; staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); - staticTextItem.glyphPositions = positions.data(); + staticTextItem.glyphPositions = positions; extended->drawStaticTextItem(&staticTextItem); } else { @@ -5766,7 +5875,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit textItem.glyphs.numGlyphs = glyphCount; textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray)); - textItem.glyphs.offsets = positions.data(); + textItem.glyphs.offsets = positions; textItem.glyphs.advances_x = advances.data(); textItem.glyphs.advances_y = advances.data(); textItem.glyphs.justifications = glyphJustifications.data(); @@ -5774,6 +5883,21 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit engine->drawTextItem(QPointF(0, 0), textItem); } + + QTextItemInt::RenderFlags flags; + if (state->font.underline()) + flags |= QTextItemInt::Underline; + if (state->font.overline()) + flags |= QTextItemInt::Overline; + if (state->font.strikeOut()) + flags |= QTextItemInt::StrikeOut; + + drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), + fontEngine, + (state->font.underline() + ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline), + flags, width.toReal(), QTextCharFormat()); } /*! @@ -5907,7 +6031,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText // Recreate the layout of the static text because the matrix or font has changed if (staticTextNeedsReinit) - staticText_d->init(); + staticText_d->init(); if (transformedPosition != staticText_d->position) { // Translate to actual position QFixed fx = QFixed::fromReal(transformedPosition.x()); @@ -6308,7 +6432,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat) { if (underlineStyle == QTextCharFormat::NoUnderline @@ -6696,7 +6820,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true); #endif qreal sw = pixmap.width(); @@ -7996,6 +8120,9 @@ start_lengthVariant: engine.option = *option; } + if (engine.option.tabStop() < 0 && tabstops > 0) + engine.option.setTabStop(tabstops); + engine.option.setTextDirection(layout_direction); if (tf & Qt::AlignJustify) engine.option.setAlignment(Qt::AlignJustify); diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index edfb67e..96305e3 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -79,6 +79,7 @@ class QTextItem; class QMatrix; class QTransform; class QStaticText; +class QGlyphs; class QPainterPrivateDeleter; @@ -221,6 +222,8 @@ public: void setClipping(bool enable); bool hasClipping() const; + QRectF clipBoundingRect() const; + void save(); void restore(); @@ -396,6 +399,8 @@ public: void setLayoutDirection(Qt::LayoutDirection direction); Qt::LayoutDirection layoutDirection() const; + void drawGlyphs(const QPointF &position, const QGlyphs &glyphs); + void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(int left, int top, const QStaticText &staticText); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 9362dbe..a61f5ca 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QEmulationPaintEngine; class QPaintEngineEx; +struct QFixedPoint; struct QTLWExtra; @@ -228,7 +229,7 @@ public: void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw); void drawStretchedGradient(const QPainterPath &path, DrawOperation operation); void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation); - void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount); + void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount); void updateMatrix(); void updateInvMatrix(); diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index f8f8afb..c92d8d5 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -62,8 +62,8 @@ typedef int Q16Dot16; #define SPAN_BUFFER_SIZE 256 -#define COORD_ROUNDING 1 // 0: round up, 1: round down -#define COORD_OFFSET 32 // 26.6, 32 is half a pixel +#define COORD_ROUNDING 0 // 0: round up, 1: round down +#define COORD_OFFSET 0 // 26.6, 32 is half a pixel class QSpanBuffer { public: @@ -718,7 +718,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, QPointF pa = a; QPointF pb = b; - QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; + QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; if (squareCap) offs += QPointF(offs.y(), offs.x()); const QRectF clip(d->clipRect.topLeft() - offs, d->clipRect.bottomRight() + QPoint(1, 1) + offs); diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 631a9cf..376219b 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -126,8 +126,13 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const return; rowHeight += margin * 2 + paddingDoubled; - if (isNull()) - createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight)); + + if (m_w == 0) { + if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH) + m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; + else + m_w = qt_next_power_of_two(fontEngine->maxCharWidth()); + } // now actually use the coords and paint the wanted glyps into cache. QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin(); @@ -142,26 +147,50 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const m_cy += m_currentRowHeight + paddingDoubled; m_currentRowHeight = 0; // New row } - if (m_cy + c.h > m_h) { - int new_height = m_h*2; - while (new_height < m_cy + c.h) - new_height *= 2; - // if no room in the current texture - realloc a larger texture - resizeTextureData(m_w, new_height); - m_h = new_height; - } c.x = m_cx; c.y = m_cy; - fillTexture(c, iter.key()); coords.insert(iter.key(), c); + m_pendingGlyphs.insert(iter.key(), c); m_cx += c.w + paddingDoubled; ++iter; } +} +void QTextureGlyphCache::fillInPendingGlyphs() +{ + if (m_pendingGlyphs.isEmpty()) + return; + + int requiredHeight = 0; + { + QHash<glyph_t, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + Coord c = iter.value(); + requiredHeight = qMax(requiredHeight, c.y + c.h); + ++iter; + } + } + + if (requiredHeight > m_h) { + if (isNull()) + createCache(m_w, qt_next_power_of_two(requiredHeight)); + else + resizeCache(m_w, qt_next_power_of_two(requiredHeight)); + } + + { + QHash<glyph_t, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + fillTexture(iter.value(), iter.key()); + + ++iter; + } + } + m_pendingGlyphs.clear(); } QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index a818978..0770ed4 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -94,6 +94,7 @@ public: void populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions); + void fillInPendingGlyphs(); virtual void createTextureData(int width, int height) = 0; virtual void resizeTextureData(int width, int height) = 0; @@ -108,7 +109,14 @@ public: createTextureData(width, height); } - inline bool isNull() const { return m_w <= 0 || m_h <= 0; } + inline void resizeCache(int width, int height) + { + resizeTextureData(width, height); + m_w = width; + m_h = height; + } + + inline bool isNull() const { return m_h == 0; } QHash<glyph_t, Coord> coords; @@ -117,6 +125,8 @@ public: protected: QFontEngine *m_current_fontengine; + QHash<glyph_t, Coord> m_pendingGlyphs; + int m_w; // image width int m_h; // image height int m_cx; // current x diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index eee6bef..6a2cb1e 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -248,10 +248,6 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_MAC -// qDebug() << "Flushing" << widget << rgn << offset; - -// d->image->image.save("flush.png"); - Q_UNUSED(offset); // Get a context for the widget. #ifndef QT_MAC_USE_COCOA @@ -282,20 +278,19 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGImageRef subImage = CGImageCreateWithImageInRect(image, area); qt_mac_drawCGImage(context, &area, subImage); + CGImageRelease(subImage); CGImageRelease(image); -// CGSize size = { d->image->image.width(), d->image->image.height() }; -// CGLayerRef layer = CGLayerCreateWithContext(d->image->cg, size, 0); -// CGPoint pt = { 0, 0 }; -// CGContextDrawLayerAtPoint(context, pt, layer); -// CGLayerRelease(layer); - - // Restore context. - CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); +#else + CGContextFlush(context); #endif + + // Restore context. + CGContextRestoreGState(context); + #endif // Q_WS_MAC #ifdef Q_OS_SYMBIAN diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 8bac1f5..d4dcf7d 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -77,7 +77,8 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) } // We create empty CFbsBitmap here -> it will be resized in setGeometry - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new + Q_CHECK_PTR(bitmap); qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType); diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index ada5293..de50ef8 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -3763,6 +3763,7 @@ int QCleanlooksStyle::pixelMetric(PixelMetric metric, const QStyleOption *option break; case PM_MenuBarItemSpacing: ret = 6; + break; case PM_MenuBarHMargin: ret = 0; break; diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 671a888..556e0f3 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1642,7 +1642,7 @@ bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e) case QEvent::FocusOut: case QEvent::Show: case QEvent::WindowActivate: { - QList<QPushButton *> list = qFindChildren<QPushButton *>(btn->window()); + QList<QPushButton *> list = btn->window()->findChildren<QPushButton *>(); for (int i = 0; i < list.size(); ++i) { QPushButton *pBtn = list.at(i); if ((e->type() == QEvent::FocusOut @@ -5538,6 +5538,57 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, // hack to work around horrible sizeHint() code in QAbstractSpinBox sz.setHeight(sz.height() - 3); break; + case QStyle::CT_TabWidget: + // the size between the pane and the "contentsRect" (+4,+4) + // (the "contentsRect" is on the inside of the pane) + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + /** + This is supposed to show the relationship between the tabBar and + the stack widget of a QTabWidget. + Unfortunately ascii is not a good way of representing graphics..... + PS: The '=' line is the painted frame. + + top ---+ + | + | + | + | vvv just outside the painted frame is the "pane" + - -|- - - - - - - - - - <-+ + TAB BAR +=====^============ | +2 pixels + - - -|- - -|- - - - - - - <-+ + | | ^ ^^^ just inside the painted frame is the "contentsRect" + | | | + | overlap | + | | | + bottom ------+ <-+ +14 pixels + | + v + ------------------------------ <- top of stack widget + + + To summarize: + * 2 is the distance between the pane and the contentsRect + * The 14 and the 1's are the distance from the contentsRect to the stack widget. + (same value as used in SE_TabWidgetTabContents) + * overlap is how much the pane should overlap the tab bar + */ + // then add the size between the stackwidget and the "contentsRect" + + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + QSize extra(0,0); + const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); + const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; + + if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { + extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); + } else { + extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); + } + sz+= extra; + } + + break; case QStyle::CT_TabBarTab: if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 20d9bd9..4690a71 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -1054,7 +1054,7 @@ void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOpt bool reverse = option->direction == Qt::RightToLeft; QStyleOptionFrame frameOpt; #ifndef QT_NO_LINEEDIT - if (QLineEdit *lineedit = qFindChild<QLineEdit *>(widget)) + if (QLineEdit *lineedit = widget->findChild<QLineEdit *>()) frameOpt.initFrom(lineedit); #else Q_UNUSED(widget) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index e28403b..b11fb2b 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -1412,7 +1412,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, bool isScrollBarVisible = false; int scrollBarWidth = 0; - QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget); + QList<QScrollBar *> scrollBars = widget->findChildren<QScrollBar *>(); for (int i = 0; i < scrollBars.size(); ++i) { QScrollBar *scrollBar = scrollBars.at(i); if (scrollBar && scrollBar->orientation() == Qt::Vertical) { diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 92e2c81..4be439d 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2342,7 +2342,7 @@ static QWidget *embeddedWidget(QWidget *w) #ifndef QT_NO_SPINBOX if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w)) - return qFindChild<QLineEdit *>(sb); + return sb->findChild<QLineEdit *>(); #endif #ifndef QT_NO_SCROLLAREA @@ -2583,7 +2583,7 @@ void QStyleSheetStyle::unsetPalette(QWidget *w) } QVariant oldFont = w->property("_q_styleSheetWidgetFont"); if (oldFont.isValid()) { - w->setFont(qVariantValue<QFont>(oldFont)); + w->setFont(qvariant_cast<QFont>(oldFont)); } if (autoFillDisabledWidgets->contains(w)) { embeddedWidget(w)->setAutoFillBackground(true); @@ -2795,7 +2795,7 @@ void QStyleSheetStyle::polish(QPalette &pal) void QStyleSheetStyle::repolish(QWidget *w) { - QList<const QWidget *> children = qFindChildren<const QWidget *>(w, QString()); + QList<const QWidget *> children = w->findChildren<const QWidget *>(QString()); children.append(w); styleSheetCache->remove(w); updateWidgets(children); @@ -3048,6 +3048,13 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window); drawItemText(p, labelRect, alignment, pal, gb->state & State_Enabled, gb->text, QPalette::WindowText); + + if (gb->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*gb); + fropt.rect = labelRect; + drawPrimitive(PE_FrameFocusRect, &fropt, p, w); + } } return; @@ -5074,7 +5081,7 @@ QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon, if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) - return qVariantValue<QIcon>(rule.styleHint(s)); + return qvariant_cast<QIcon>(rule.styleHint(s)); } return baseStyle()->standardIcon(standardIcon, opt, w); } @@ -5092,7 +5099,7 @@ QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QS if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) { - QIcon icon = qVariantValue<QIcon>(rule.styleHint(s)); + QIcon icon = qvariant_cast<QIcon>(rule.styleHint(s)); return icon.pixmap(16, 16); // ###: unhard-code this if someone complains } } @@ -5186,7 +5193,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi case SH_ComboBox_PopupFrameStyle: #ifndef QT_NO_COMBOBOX if (qobject_cast<const QComboBox *>(w)) { - QAbstractItemView *view = qFindChild<QAbstractItemView *>(w); + QAbstractItemView *view = w->findChild<QAbstractItemView *>(); if (view) { view->ensurePolished(); QRenderRule subRule = renderRule(view, PseudoElement_None); diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp index b027005..bd7246a 100644 --- a/src/gui/styles/qwindowscestyle.cpp +++ b/src/gui/styles/qwindowscestyle.cpp @@ -2294,6 +2294,7 @@ int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QW break; case SH_EtchDisabledText: ret = false; + break; case SH_RequestSoftwareInputPanel: ret = RSIP_OnMouseClick; break; diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 579dd0b..8f1accb 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -175,7 +175,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) widget = widget->window(); // Alt has been pressed - find all widgets that care - QList<QWidget *> l = qFindChildren<QWidget *>(widget); + QList<QWidget *> l = widget->findChildren<QWidget *>(); for (int pos=0 ; pos < l.size() ; ++pos) { QWidget *w = l.at(pos); if (w->isWindow() || !w->isVisible() || @@ -198,7 +198,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) // Update state and repaint the menu bars. d->alt_down = false; #ifndef QT_NO_MENUBAR - QList<QMenuBar *> l = qFindChildren<QMenuBar *>(widget); + QList<QMenuBar *> l = widget->findChildren<QMenuBar *>(); for (int i = 0; i < l.size(); ++i) l.at(i)->update(); #endif @@ -1160,7 +1160,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid if (!menuBar && qobject_cast<const QMenu *>(widget)) { QWidget *w = QApplication::activeWindow(); if (w && w != widget) - menuBar = qFindChild<QMenuBar *>(w); + menuBar = w->findChild<QMenuBar *>(); } // If we paint a menu bar draw underlines if is in the keyboardState if (menuBar) { diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 8511592..8cb57d5 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -841,10 +841,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt const QDialogButtonBox *buttonBox = 0; if (qobject_cast<const QMessageBox *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<const QInputDialog *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); #endif // QT_NO_INPUTDIALOG if (buttonBox) { @@ -2395,14 +2395,14 @@ void QWindowsVistaStyle::polish(QWidget *widget) } } else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } @@ -2434,14 +2434,14 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 8743807..4189c78 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -4054,7 +4054,7 @@ void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) bufferPos += sprintf(bufferPos, "\n};\n\n"); printf(bufferDump); - delete bufferDump; + delete[] bufferDump; ++pCount; } } diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index b3d2526..3fc6722 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -403,7 +403,7 @@ int ValueExtractor::lengthValue(const Declaration &decl) if (decl.d->values.count() < 1) return 0; LengthData data = lengthValue(decl.d->values.at(0)); - decl.d->parsed = qVariantFromValue<LengthData>(data); + decl.d->parsed = QVariant::fromValue<LengthData>(data); return lengthValueFromData(data,f); } @@ -435,7 +435,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m) QList<QVariant> v; for (i = 0; i < 4; i++) { - v += qVariantFromValue<LengthData>(datas[i]); + v += QVariant::fromValue<LengthData>(datas[i]); m[i] = lengthValueFromData(datas[i], f); } decl.d->parsed = v; @@ -541,7 +541,7 @@ QSize ValueExtractor::sizeValue(const Declaration &decl) else x[1] = x[0]; QList<QVariant> v; - v << qVariantFromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); + v << QVariant::fromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); decl.d->parsed = v; return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f)); } @@ -916,7 +916,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.width = lengthValue(decl.d->values.at(i)); *width = lengthValueFromData(data.width, f); if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } @@ -925,7 +925,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord if (data.style != BorderStyle_Unknown) { *style = data.style; if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } else { @@ -935,7 +935,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.color = parseBrushValue(decl.d->values.at(i), pal); *color = brushFromData(data.color, pal); if (data.color.type != BrushData::DependsOnThePalette) - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); } static void parseShorthandBackgroundProperty(const QVector<Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) @@ -1032,16 +1032,8 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal); *brush = brushFromData(brushData, pal); if (brushData.type != BrushData::DependsOnThePalette) { -#if defined Q_CC_MSVC && _MSC_VER <= 1300 - BackgroundData data; - data.brush = brushData; - data.image = *image; - data.repeat = *repeat; - data.alignment = *alignment; -#else BackgroundData data = { brushData, *image, *repeat, *alignment }; -#endif - decl.d->parsed = qVariantFromValue<BackgroundData>(data); + decl.d->parsed = QVariant::fromValue<BackgroundData>(data); } } break; @@ -1319,10 +1311,10 @@ QColor Declaration::colorValue(const QPalette &pal) const ColorData color = parseColorValue(d->values.at(0)); if(color.type == ColorData::Role) { - d->parsed = qVariantFromValue<int>(color.role); + d->parsed = QVariant::fromValue<int>(color.role); return pal.color((QPalette::ColorRole)(color.role)); } else { - d->parsed = qVariantFromValue<QColor>(color.color); + d->parsed = QVariant::fromValue<QColor>(color.color); return color.color; } } @@ -1342,11 +1334,11 @@ QBrush Declaration::brushValue(const QPalette &pal) const BrushData data = parseBrushValue(d->values.at(0), pal); if(data.type == BrushData::Role) { - d->parsed = qVariantFromValue<int>(data.role); + d->parsed = QVariant::fromValue<int>(data.role); return pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) - d->parsed = qVariantFromValue<QBrush>(data.brush); + d->parsed = QVariant::fromValue<QBrush>(data.brush); return data.brush; } } @@ -1376,11 +1368,11 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const continue; BrushData data = parseBrushValue(d->values.at(i), pal); if(data.type == BrushData::Role) { - v += qVariantFromValue<int>(data.role); + v += QVariant::fromValue<int>(data.role); c[i] = pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) { - v += qVariantFromValue<QBrush>(data.brush); + v += QVariant::fromValue<QBrush>(data.brush); } else { v += QVariant(); } @@ -1453,7 +1445,7 @@ QSize Declaration::sizeValue() const else x[1] = x[0]; QSize size(x[0], x[1]); - d->parsed = qVariantFromValue<QSize>(size); + d->parsed = QVariant::fromValue<QSize>(size); return size; } @@ -1475,7 +1467,7 @@ QRect Declaration::rectValue() const if (args.count() != 4) return QRect(); QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); - d->parsed = qVariantFromValue<QRect>(rect); + d->parsed = QVariant::fromValue<QRect>(rect); return rect; } @@ -1496,10 +1488,10 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const for (i = 0; i < qMin(d->values.count(), 4); i++) { ColorData color = parseColorValue(d->values.at(i)); if(color.type == ColorData::Role) { - v += qVariantFromValue<int>(color.role); + v += QVariant::fromValue<int>(color.role); c[i] = pal.color((QPalette::ColorRole)(color.role)); } else { - v += qVariantFromValue<QColor>(color.color); + v += QVariant::fromValue<QColor>(color.color); c[i] = color.color; } } @@ -1691,7 +1683,7 @@ QIcon Declaration::iconValue() const i++; } - d->parsed = qVariantFromValue<QIcon>(icon); + d->parsed = QVariant::fromValue<QIcon>(icon); return icon; } diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 2cc41e1..f941d1e 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -315,6 +315,7 @@ private: friend class QPainterReplayer; friend class QPaintBufferEngine; friend class QCommandLinkButtonPrivate; + friend class QFontEngine; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 470c109..646a8b8 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -192,6 +192,11 @@ public: QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); } QFontPrivate *smallCapsFontPrivate() const; + static QFontPrivate *get(const QFont &font) + { + return font.d.data(); + } + void resolve(uint mask, const QFontPrivate *other); private: QFontPrivate &operator=(const QFontPrivate &) { return *this; } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index e6c36a4..2b26638 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -75,10 +75,6 @@ # define FM_DEBUG if (false) qDebug #endif -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) -# define for if(0){}else for -#endif - QT_BEGIN_NAMESPACE #define SMOOTH_SCALABLE 0xffff diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 194c5f3..3f6b409 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -185,10 +185,6 @@ QFontEngine::QFontEngine() QFontEngine::~QFontEngine() { - for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), - end = m_glyphCaches.constEnd(); it != end; ++it) { - delete it->cache; - } m_glyphCaches.clear(); qHBFreeFace(hbFace); } @@ -242,6 +238,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix return metrics; } +QFont QFontEngine::createExplicitFont() const +{ + return createExplicitFontWithName(fontDef.family); +} + +QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const +{ + QFont font(familyName); + font.setStyleStrategy(QFont::NoFontMerging); + font.setWeight(fontDef.weight); + font.setItalic(fontDef.style == QFont::StyleItalic); + if (fontDef.pointSize < 0) + font.setPixelSize(fontDef.pixelSize); + else + font.setPointSizeF(fontDef.pointSize); + return font; +} + QFixed QFontEngine::xHeight() const { QGlyphLayoutArray<8> glyphs; @@ -716,14 +730,16 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) { Q_ASSERT(data); - GlyphCacheEntry entry = { key, data }; + GlyphCacheEntry entry; + entry.context = key; + entry.cache = data; if (m_glyphCaches.contains(entry)) return; // Limit the glyph caches to 4. This covers all 90 degree rotations and limits // memory use when there is continous or random rotation if (m_glyphCaches.size() == 4) - delete m_glyphCaches.takeLast().cache; + m_glyphCaches.removeLast(); m_glyphCaches.push_front(entry); @@ -732,7 +748,7 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const { for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { - QFontEngineGlyphCache *c = it->cache; + QFontEngineGlyphCache *c = it->cache.data(); if (key == it->context && type == c->cacheType() && qtransform_equals_no_translate(c->m_transform, transform)) { diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 2c4fbab..7a8b1e5 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -756,9 +756,18 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph return g; int load_flags = FT_LOAD_DEFAULT | default_load_flags; + int load_target = default_hint_style == HintLight + ? FT_LOAD_TARGET_LIGHT + : FT_LOAD_TARGET_NORMAL; + if (set->outline_drawing) load_flags = FT_LOAD_NO_BITMAP; + if (default_hint_style == HintNone) + load_flags |= FT_LOAD_NO_HINTING; + else + load_flags |= load_target; + // apply our matrix to this, but note that the metrics will not be affected by this. FT_Face face = lockFace(); FT_Matrix matrix = this->matrix; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 91b6082..f898fb8 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -656,6 +656,12 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position } } +QFont QCoreTextFontEngine::createExplicitFont() const +{ + QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont)); + return createExplicitFontWithName(familyName); +} + QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) { const glyph_metrics_t br = boundingBox(glyph); @@ -1591,6 +1597,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint DisposeATSCubicClosePathUPP(closePath); } +QFont QFontEngineMac::createExplicitFont() const +{ + FMFont fmFont = FMGetFontFromATSFontRef(fontID); + + FMFontFamily fmFamily; + FMFontStyle fmStyle; + QString familyName; + if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { + ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); + QCFString cfFamilyName;; + ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); + familyName = cfFamilyName; + } else { + QCFString cfFontName; + ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName); + familyName = cfFontName; + } + + return createExplicitFontWithName(familyName); +} + void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 922acfb..4e518d6 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -173,6 +173,10 @@ public: #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); + + /* Creates a QFont object to represent this particular QFontEngine */ + virtual QFont createExplicitFont() const; + void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions); @@ -252,12 +256,13 @@ public: int glyphFormat; protected: + QFont createExplicitFontWithName(const QString &familyName) const; static const QVector<QRgb> &grayPalette(); private: struct GlyphCacheEntry { void *context; - QFontEngineGlyphCache *cache; + QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache; bool operator==(const GlyphCacheEntry &other) { return context == other.context && cache == other.cache; } }; @@ -454,7 +459,7 @@ public: virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); virtual qreal minRightBearing() const; virtual qreal minLeftBearing() const; - + virtual QFont createExplicitFont() const; private: QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); @@ -520,6 +525,8 @@ public: virtual qreal maxCharWidth() const; virtual QFixed averageCharWidth() const; + virtual QFont createExplicitFont() const; + virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags); diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 52a1fe7..a25970b 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -122,7 +122,8 @@ QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); TInt error = KErrNone; TInt tableByteLength = 0; - TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); QByteArray result(static_cast<const char*>(table), tableByteLength); m_trueTypeExtension->ReleaseTrueTypeTable(table); return result; @@ -136,8 +137,8 @@ bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *len bool result = true; TInt error = KErrNone; TInt tableByteLength; - TAny *table = - q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); if (error != KErrNone) { return false; diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp index b7e4be2..aee21f6 100644 --- a/src/gui/text/qfontengine_x11.cpp +++ b/src/gui/text/qfontengine_x11.cpp @@ -992,7 +992,7 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s face_id.filename = file_name; face_id.index = face_index; - canUploadGlyphsToServer = qApp->thread() == QThread::currentThread(); + canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread()); subpixelType = Subpixel_None; if (antialias) { diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index 7b82b46..eba16f7 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE -class QFontEngineGlyphCache +class QFontEngineGlyphCache: public QSharedData { public: enum Type { diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index d02e841..f2591ce 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -443,6 +443,21 @@ bool QFontMetrics::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetrics::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1315,6 +1330,21 @@ bool QFontMetricsF::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetricsF::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1779,7 +1809,7 @@ qreal QFontMetricsF::lineWidth() const Use the boundingRect() function in combination with QString::left() instead. - + \oldcode QRect rect = boundingRect(text, len); \newcode diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 2518b54..9911ad2 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -85,6 +85,7 @@ public: int averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; int leftBearing(QChar) const; int rightBearing(QChar) const; @@ -162,6 +163,7 @@ public: qreal averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; qreal leftBearing(QChar) const; qreal rightBearing(QChar) const; diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp new file mode 100644 index 0000000..2447752 --- /dev/null +++ b/src/gui/text/qglyphs.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglyphs.h" +#include "qglyphs_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGlyphs + \brief the QGlyphs class provides direct access to the internal glyphs in a font + \since 4.8 + + \ingroup text + \mainclass + + When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points + into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode + representation of the text and the QFont object will in this case serve as a convenient + abstraction that hides the details of what actually takes place when displaying the text + on-screen. For instance, by the time the text actually reaches the screen, it may be represented + by a set of fonts in addition to the one specified by the user, e.g. in case the originally + selected font did not support all the writing systems contained in the text. + + Under certain circumstances, it can be useful as an application developer to have more low-level + control over which glyphs in a specific font are drawn to the screen. This could for instance + be the case in applications that use an external font engine and text shaper together with Qt. + QGlyphs provides an interface to the raw data needed to get text on the screen. It + contains a list of glyph indexes, a position for each glyph and a font. + + It is the user's responsibility to ensure that the selected font actually contains the + provided glyph indexes. + + QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs + objects, and QPainter::drawGlyphs() can be used to draw the glyphs. +*/ + + +/*! + Constructs an empty QGlyphs object. +*/ +QGlyphs::QGlyphs() : d(new QGlyphsPrivate) +{ +} + +/*! + Constructs a QGlyphs object which is a copy of \a other. +*/ +QGlyphs::QGlyphs(const QGlyphs &other) +{ + d = other.d; +} + +/*! + Destroys the QGlyphs. +*/ +QGlyphs::~QGlyphs() +{ + // Required for QExplicitlySharedDataPointer +} + +/*! + \internal +*/ +void QGlyphs::detach() +{ + if (d->ref != 1) + d.detach(); +} + +/*! + Assigns \a other to this QGlyphs object. +*/ +QGlyphs &QGlyphs::operator=(const QGlyphs &other) +{ + d = other.d; + return *this; +} + +/*! + Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes, + the list of positions and the font are all equal, otherwise returns false. +*/ +bool QGlyphs::operator==(const QGlyphs &other) const +{ + return ((d == other.d) + || (d->glyphIndexes == other.d->glyphIndexes + && d->glyphPositions == other.d->glyphPositions + && d->font == other.d->font)); +} + +/*! + Compares \a other to this QGlyphs object. Returns true if any of the list of glyph + indexes, the list of positions or the font are different, otherwise returns false. +*/ +bool QGlyphs::operator!=(const QGlyphs &other) const +{ + return !(*this == other); +} + +/*! + \internal + + Adds together the lists of glyph indexes and positions in \a other and this QGlyphs + object and returns the result. The font in the returned QGlyphs will be the same as in + this QGlyphs object. +*/ +QGlyphs QGlyphs::operator+(const QGlyphs &other) const +{ + QGlyphs ret(*this); + ret += other; + return ret; +} + +/*! + \internal + + Appends the glyph indexes and positions in \a other to this QGlyphs object and returns + a reference to the current object. +*/ +QGlyphs &QGlyphs::operator+=(const QGlyphs &other) +{ + detach(); + + d->glyphIndexes += other.d->glyphIndexes; + d->glyphPositions += other.d->glyphPositions; + + return *this; +} + +/*! + Returns the font selected for this QGlyphs object. + + \sa setFont() +*/ +QFont QGlyphs::font() const +{ + return d->font; +} + +/*! + Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly + resolvable font which defines glyphs for the specified glyph indexes. + + \sa font(), setGlyphIndexes() +*/ +void QGlyphs::setFont(const QFont &font) +{ + detach(); + d->font = font; +} + +/*! + Returns the glyph indexes for this QGlyphs object. + + \sa setGlyphIndexes(), setPositions() +*/ +QVector<quint32> QGlyphs::glyphIndexes() const +{ + return d->glyphIndexes; +} + +/*! + Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must + be valid for the selected font. +*/ +void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes) +{ + detach(); + d->glyphIndexes = glyphIndexes; +} + +/*! + Returns the position of the edge of the baseline for each glyph in this set of glyph indexes. +*/ +QVector<QPointF> QGlyphs::positions() const +{ + return d->glyphPositions; +} + +/*! + Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to + \a positions. +*/ +void QGlyphs::setPositions(const QVector<QPointF> &positions) +{ + detach(); + d->glyphPositions = positions; +} + +/*! + Clears all data in the QGlyphs object. +*/ +void QGlyphs::clear() +{ + detach(); + d->glyphPositions = QVector<QPointF>(); + d->glyphIndexes = QVector<quint32>(); + d->font = QFont(); +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h new file mode 100644 index 0000000..282ecb4 --- /dev/null +++ b/src/gui/text/qglyphs.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_H +#define QGLYPHS_H + +#include <QtCore/qsharedpointer.h> +#include <QtCore/qvector.h> +#include <QtCore/qpoint.h> +#include <QtGui/qfont.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGlyphsPrivate; +class Q_GUI_EXPORT QGlyphs +{ +public: + QGlyphs(); + QGlyphs(const QGlyphs &other); + ~QGlyphs(); + + QFont font() const; + void setFont(const QFont &font); + + QVector<quint32> glyphIndexes() const; + void setGlyphIndexes(const QVector<quint32> &glyphIndexes); + + QVector<QPointF> positions() const; + void setPositions(const QVector<QPointF> &positions); + + void clear(); + + QGlyphs &operator=(const QGlyphs &other); + bool operator==(const QGlyphs &other) const; + bool operator!=(const QGlyphs &other) const; + +private: + friend class QGlyphsPrivate; + friend class QTextLine; + + QGlyphs operator+(const QGlyphs &other) const; + QGlyphs &operator+=(const QGlyphs &other); + + void detach(); + QExplicitlySharedDataPointer<QGlyphsPrivate> d; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGLYPHS_H diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h new file mode 100644 index 0000000..c39f5d0 --- /dev/null +++ b/src/gui/text/qglyphs_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_P_H +#define QGLYPHS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include <qfont.h> +#include "qglyphs.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGlyphsPrivate: public QSharedData +{ +public: + QGlyphsPrivate() + { + } + + QGlyphsPrivate(const QGlyphsPrivate &other) + : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font) + { + } + + QVector<quint32> glyphIndexes; + QVector<QPointF> glyphPositions; + QFont font; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGLYPHS_P_H diff --git a/src/gui/text/qpfutil.cpp b/src/gui/text/qpfutil.cpp index 376f49c..7f8c58e 100644 --- a/src/gui/text/qpfutil.cpp +++ b/src/gui/text/qpfutil.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -static QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { +static const QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { QFontEngineQPF::StringType, // FontName QFontEngineQPF::StringType, // FileName QFontEngineQPF::UInt32Type, // FileIndex diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 5fe0c0c..441a8c8 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -2900,7 +2900,7 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget if (widget) style = widget->style(); style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); - selection.format = qVariantValue<QTextFormat>(ret.variant).toCharFormat(); + selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); } else { QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive; selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight)); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 195dc28..42d6c66 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1972,6 +1972,8 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) if (fi.exists()) { resourceUrl = QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name); + } else if (currentURL.isEmpty()) { + resourceUrl.setScheme(QLatin1String("file")); } } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8d6dd6c..4135831 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1389,6 +1389,7 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + feCache.reset(); } void QTextEngine::clearLineData() @@ -1785,6 +1786,13 @@ QFont QTextEngine::font(const QScriptItem &si) const return font; } +QTextEngine::FontEngineCache::FontEngineCache() +{ + reset(); +} + +//we cache the previous results of this function, as calling it numerous times with the same effective +//input is common (and hard to cache at a higher level) QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const { QFontEngine *engine = 0; @@ -1793,28 +1801,47 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix QFont font = fnt; if (hasFormats()) { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + feCache.prevScaledFontEngine = scaledEngine; + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); } } else { - engine = font.d->engineForScript(script); + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } if (si.analysis.flags == QScriptAnalysis::SmallCaps) { @@ -2347,30 +2374,29 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (flags & Qt::TextShowMnemonic) { itemize(); + HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); + if (!attributes) + return QString(); for (int i = 0; i < layoutData->items.size(); ++i) { QScriptItem &si = layoutData->items[i]; if (!si.num_glyphs) shape(i); - HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); - if (!attributes) - return QString(); - unsigned short *logClusters = this->logClusters(&si); QGlyphLayout glyphs = shapedGlyphs(&si); const int end = si.position + length(&si); - for (int i = si.position; i < end - 1; ++i) + for (int i = si.position; i < end - 1; ++i) { if (layoutData->string.at(i) == QLatin1Char('&')) { const int gp = logClusters[i - si.position]; glyphs.attributes[gp].dontPrint = true; attributes[i + 1].charStop = false; attributes[i + 1].whiteSpace = false; attributes[i + 1].lineBreakType = HB_NoBreak; - if (i < end - 1 - && layoutData->string.at(i + 1) == QLatin1Char('&')) + if (layoutData->string.at(i + 1) == QLatin1Char('&')) ++i; } + } } } @@ -2432,7 +2458,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (mode == Qt::ElideRight) { QFixed currentWidth; - int pos = 0; + int pos; int nextBreak = 0; do { @@ -2452,7 +2478,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int return layoutData->string.left(pos) + ellipsisText; } else if (mode == Qt::ElideLeft) { QFixed currentWidth; - int pos = layoutData->string.length(); + int pos; int nextBreak = layoutData->string.length(); do { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 4cbe81f..b5faf20 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -128,7 +128,7 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis TabOrObject = Tab, Object = 7 }; - unsigned short script : 8; + unsigned short script : 7; unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) unsigned short flags : 3; inline bool operator == (const QScriptAnalysis &other) const { @@ -385,7 +385,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed textWidth; QFixed textAdvance; int from; - signed int length : 29; + signed int length : 28; mutable uint justified : 1; mutable uint gridfitted : 1; uint hasTrailingSpaces : 1; @@ -435,7 +435,7 @@ public: uint hasBidi : 1; uint layoutState : 2; uint memory_on_stack : 1; - bool haveCharAttributes; + uint haveCharAttributes : 1; QString string; bool reallocate(int totalGlyphs); }; @@ -556,6 +556,23 @@ public: mutable QScriptLineArray lines; + struct FontEngineCache { + FontEngineCache(); + mutable QFontEngine *prevFontEngine; + mutable QFontEngine *prevScaledFontEngine; + mutable int prevScript; + mutable int prevPosition; + mutable int prevLength; + inline void reset() { + prevFontEngine = 0; + prevScaledFontEngine = 0; + prevScript = -1; + prevPosition = -1; + prevLength = -1; + } + }; + mutable FontEngineCache feCache; + QString text; QFont fnt; QTextBlock block; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 46db253..e0a4096 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -925,7 +925,7 @@ qreal QTextFormat::doubleProperty(int propertyId) const const QVariant prop = d->property(propertyId); if (prop.userType() != QVariant::Double && prop.userType() != QMetaType::Float) return 0.; - return qVariantValue<qreal>(prop); + return qvariant_cast<qreal>(prop); } /*! @@ -1895,7 +1895,7 @@ void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs) QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin(); while (iter != tabs.constEnd()) { QVariant v; - qVariantSetValue<QTextOption::Tab>(v, *iter); + v.setValue<QTextOption::Tab>(*iter); list.append(v); ++iter; } @@ -1917,7 +1917,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant); QList<QVariant>::Iterator iter = variantsList.begin(); while(iter != variantsList.end()) { - answer.append( qVariantValue<QTextOption::Tab>(*iter)); + answer.append( qvariant_cast<QTextOption::Tab>(*iter)); ++iter; } return answer; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f432b7e..3f83aee 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -52,6 +52,8 @@ #include "qtextformat_p.h" #include "qstyleoption.h" #include "qpainterpath.h" +#include "qglyphs.h" +#include "qglyphs_p.h" #include <limits.h> #include <qdebug.h> @@ -165,7 +167,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) /*! Returns the inline object's rectangle. - \sa ascent() descent() width() + \sa ascent(), descent(), width() */ QRectF QTextInlineObject::rect() const { @@ -176,7 +178,7 @@ QRectF QTextInlineObject::rect() const /*! Returns the inline object's width. - \sa ascent() descent() rect() + \sa ascent(), descent(), rect() */ qreal QTextInlineObject::width() const { @@ -186,7 +188,7 @@ qreal QTextInlineObject::width() const /*! Returns the inline object's ascent. - \sa descent() width() rect() + \sa descent(), width(), rect() */ qreal QTextInlineObject::ascent() const { @@ -196,7 +198,7 @@ qreal QTextInlineObject::ascent() const /*! Returns the inline object's descent. - \sa ascent() width() rect() + \sa ascent(), width(), rect() */ qreal QTextInlineObject::descent() const { @@ -207,18 +209,17 @@ qreal QTextInlineObject::descent() const Returns the inline object's total height. This is equal to ascent() + descent() + 1. - \sa ascent() descent() width() rect() + \sa ascent(), descent(), width(), rect() */ qreal QTextInlineObject::height() const { return eng->layoutData->items[itm].height().toReal(); } - /*! Sets the inline object's width to \a w. - \sa width() ascent() descent() rect() + \sa width(), ascent(), descent(), rect() */ void QTextInlineObject::setWidth(qreal w) { @@ -228,7 +229,7 @@ void QTextInlineObject::setWidth(qreal w) /*! Sets the inline object's ascent to \a a. - \sa ascent() setDescent() width() rect() + \sa ascent(), setDescent(), width(), rect() */ void QTextInlineObject::setAscent(qreal a) { @@ -238,7 +239,7 @@ void QTextInlineObject::setAscent(qreal a) /*! Sets the inline object's decent to \a d. - \sa descent() setAscent() width() rect() + \sa descent(), setAscent(), width(), rect() */ void QTextInlineObject::setDescent(qreal d) { @@ -246,7 +247,7 @@ void QTextInlineObject::setDescent(qreal d) } /*! - The position of the inline object within the text layout. + The position of the inline object within the text layout. */ int QTextInlineObject::textPosition() const { @@ -254,8 +255,8 @@ int QTextInlineObject::textPosition() const } /*! - Returns an integer describing the format of the inline object - within the text layout. + Returns an integer describing the format of the inline object + within the text layout. */ int QTextInlineObject::formatIndex() const { @@ -263,7 +264,7 @@ int QTextInlineObject::formatIndex() const } /*! - Returns format of the inline object within the text layout. + Returns format of the inline object within the text layout. */ QTextFormat QTextInlineObject::format() const { @@ -273,7 +274,7 @@ QTextFormat QTextInlineObject::format() const } /*! - Returns if the object should be laid out right-to-left or left-to-right. + Returns if the object should be laid out right-to-left or left-to-right. */ Qt::LayoutDirection QTextInlineObject::textDirection() const { @@ -325,7 +326,6 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const boundingRect(), and a minimumWidth() and a maximumWidth(). \sa QStaticText - */ /*! @@ -398,16 +398,19 @@ QTextLayout::~QTextLayout() Sets the layout's font to the given \a font. The layout is invalidated and must be laid out again. - \sa text() + \sa font() */ void QTextLayout::setFont(const QFont &font) { d->fnt = font; + d->feCache.reset(); } /*! Returns the current font that is used for the layout, or a default font if none is set. + + \sa setFont() */ QFont QTextLayout::font() const { @@ -441,10 +444,10 @@ QString QTextLayout::text() const } /*! - Sets the text option structure that controls the layout process to the - given \a option. + Sets the text option structure that controls the layout process to the + given \a option. - \sa textOption() QTextOption + \sa textOption() */ void QTextLayout::setTextOption(const QTextOption &option) { @@ -452,9 +455,9 @@ void QTextLayout::setTextOption(const QTextOption &option) } /*! - Returns the current text option used to control the layout process. + Returns the current text option used to control the layout process. - \sa setTextOption() QTextOption + \sa setTextOption() */ QTextOption QTextLayout::textOption() const { @@ -464,6 +467,8 @@ QTextOption QTextLayout::textOption() const /*! Sets the \a position and \a text of the area in the layout that is processed before editing occurs. + + \sa preeditAreaPosition(), preeditAreaText() */ void QTextLayout::setPreeditArea(int position, const QString &text) { @@ -492,6 +497,8 @@ void QTextLayout::setPreeditArea(int position, const QString &text) /*! Returns the position of the area in the text layout that will be processed before editing occurs. + + \sa preeditAreaText() */ int QTextLayout::preeditAreaPosition() const { @@ -500,6 +507,8 @@ int QTextLayout::preeditAreaPosition() const /*! Returns the text that is inserted in the layout before editing occurs. + + \sa preeditAreaPosition() */ QString QTextLayout::preeditAreaText() const { @@ -508,8 +517,7 @@ QString QTextLayout::preeditAreaText() const /*! - Sets the additional formats supported by the text layout to \a - formatList. + Sets the additional formats supported by the text layout to \a formatList. \sa additionalFormats(), clearAdditionalFormats() */ @@ -535,6 +543,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) } if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); + d->feCache.reset(); } /*! @@ -599,6 +608,8 @@ bool QTextLayout::cacheEnabled() const /*! Begins the layout process. + + \sa endLayout() */ void QTextLayout::beginLayout() { @@ -616,6 +627,8 @@ void QTextLayout::beginLayout() /*! Ends the layout process. + + \sa beginLayout() */ void QTextLayout::endLayout() { @@ -634,35 +647,33 @@ void QTextLayout::endLayout() d->freeMemory(); } -/*! \since 4.4 +/*! + \since 4.4 -Clears the line information in the layout. After having called -this function, lineCount() returns 0. - */ + Clears the line information in the layout. After having called + this function, lineCount() returns 0. +*/ void QTextLayout::clearLayout() { d->clearLineData(); } - /*! Returns the next valid cursor position after \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() previousCursorPosition() + \sa isValidCursorPosition(), previousCursorPosition() */ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for next cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes) - return 0; - int len = d->block.isValid() ? - (d->block.length() - 1) - : d->layoutData->string.length(); - - if (oldPos >= len) + int len = d->block.isValid() ? d->block.length() - 1 + : d->layoutData->string.length(); + Q_ASSERT(len <= d->layoutData->string.length()); + if (!attributes || oldPos < 0 || oldPos >= len) return oldPos; + if (mode == SkipCharacters) { oldPos++; while (oldPos < len && !attributes[oldPos].charStop) @@ -679,22 +690,23 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const while (oldPos < len && d->atSpace(oldPos)) oldPos++; } -// qDebug(" -> %d", oldPos); + return oldPos; } /*! Returns the first valid cursor position before \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() nextCursorPosition() + \sa isValidCursorPosition(), nextCursorPosition() */ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for previous cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes || oldPos <= 0) - return 0; + if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length()) + return oldPos; + if (mode == SkipCharacters) { oldPos--; while (oldPos && !attributes[oldPos].charStop) @@ -712,7 +724,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const oldPos--; } } -// qDebug(" -> %d", oldPos); + return oldPos; } @@ -739,7 +751,6 @@ bool QTextLayout::isValidCursorPosition(int pos) const return attributes[pos].charStop; } - /*! Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise returns an invalid text line. @@ -801,7 +812,7 @@ int QTextLayout::lineCount() const /*! Returns the \a{i}-th line of text in this text layout. - \sa lineCount() lineForTextPosition() + \sa lineCount(), lineForTextPosition() */ QTextLine QTextLayout::lineAt(int i) const { @@ -811,7 +822,7 @@ QTextLine QTextLayout::lineAt(int i) const /*! Returns the line that contains the cursor position specified by \a pos. - \sa isValidCursorPosition() lineAt() + \sa isValidCursorPosition(), lineAt() */ QTextLine QTextLayout::lineForTextPosition(int pos) const { @@ -902,8 +913,9 @@ qreal QTextLayout::maximumWidth() const return d->maxWidth.toReal(); } + /*! - \internal + \internal */ void QTextLayout::setFlags(int flags) { @@ -1028,6 +1040,35 @@ QScriptItem &QTextLineItemIterator::next() return *si; } +static QFixed offsetInLigature(const unsigned short *logClusters, + const QGlyphLayout &glyphs, + int pos, int max, int glyph_pos) +{ + int offsetInCluster = 0; + for (int i = pos - 1; i >= 0; i--) { + if (logClusters[i] == glyph_pos) + offsetInCluster++; + else + break; + } + + // in the case that the offset is inside a (multi-character) glyph, + // interpolate the position. + if (offsetInCluster > 0) { + int clusterLength = 0; + for (int i = pos - offsetInCluster; i < max; i++) { + if (logClusters[i] == glyph_pos) + clusterLength++; + else + break; + } + if (clusterLength) + return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; + } + + return 0; +} + bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const { *selectionX = *selectionWidth = 0; @@ -1067,8 +1108,19 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec swidth += glyphs.effectiveAdvance(g); } - *selectionX = x + soff; - *selectionWidth = swidth; + // If the starting character is in the middle of a ligature, + // selection should only contain the right part of that ligature + // glyph, so we need to get the width of the left part here and + // add it to *selectionX + QFixed leftOffsetInLigature = offsetInLigature(logClusters, glyphs, from, + to, start_glyph); + *selectionX = x + soff + leftOffsetInLigature; + *selectionWidth = swidth - leftOffsetInLigature; + // If the ending character is also part of a ligature, swidth does + // not contain that part yet, we also need to find out the width of + // that left part + *selectionWidth += offsetInLigature(logClusters, glyphs, to, + eng->length(item), end_glyph); } return true; } @@ -1114,9 +1166,26 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) return clip.isValid() ? (rect & clip) : rect; } + /*! - Draws the whole layout on the painter \a p at the position specified by - \a pos. + Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an + expensive function, and should not be called in a time sensitive context. + + \since 4.8 + + \sa draw(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextLayout::glyphs() const +{ + QList<QGlyphs> glyphs; + for (int i=0; i<d->lines.size(); ++i) + glyphs += QTextLine(i, d).glyphs(-1, -1); + + return glyphs; +} + +/*! + Draws the whole layout on the painter \a p at the position specified by \a pos. The rendered layout includes the given \a selections and is clipped within the rectangle specified by \a clip. */ @@ -1290,12 +1359,12 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const - \overload + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const + \overload - Draws a text cursor with the current pen at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const { @@ -1303,11 +1372,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const - Draws a text cursor with the current pen and the specified \a width at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen and the specified \a width at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const { @@ -1438,7 +1507,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition /*! Returns the line's bounding rectangle. - \sa x() y() textLength() width() + \sa x(), y(), textLength(), width() */ QRectF QTextLine::rect() const { @@ -1464,7 +1533,7 @@ QRectF QTextLine::naturalTextRect() const /*! Returns the line's x position. - \sa rect() y() textLength() width() + \sa rect(), y(), textLength(), width() */ qreal QTextLine::x() const { @@ -1474,7 +1543,7 @@ qreal QTextLine::x() const /*! Returns the line's y position. - \sa x() rect() textLength() width() + \sa x(), rect(), textLength(), width() */ qreal QTextLine::y() const { @@ -1484,7 +1553,7 @@ qreal QTextLine::y() const /*! Returns the line's width as specified by the layout() function. - \sa naturalTextWidth() x() y() textLength() rect() + \sa naturalTextWidth(), x(), y(), textLength(), rect() */ qreal QTextLine::width() const { @@ -1495,7 +1564,7 @@ qreal QTextLine::width() const /*! Returns the line's ascent. - \sa descent() height() + \sa descent(), height() */ qreal QTextLine::ascent() const { @@ -1505,7 +1574,7 @@ qreal QTextLine::ascent() const /*! Returns the line's descent. - \sa ascent() height() + \sa ascent(), height() */ qreal QTextLine::descent() const { @@ -1517,7 +1586,7 @@ qreal QTextLine::descent() const if leading is not included. If leading is included, this equals to ascent() + descent() + leading() + 1. - \sa ascent() descent() leading() setLeadingIncluded() + \sa ascent(), descent(), leading(), setLeadingIncluded() */ qreal QTextLine::height() const { @@ -1529,24 +1598,25 @@ qreal QTextLine::height() const Returns the line's leading. - \sa ascent() descent() height() + \sa ascent(), descent(), height() */ qreal QTextLine::leading() const { return eng->lines[i].leading.toReal(); } -/*! \since 4.6 +/*! + \since 4.6 - Includes positive leading into the line's height if \a included is true; - otherwise does not include leading. + Includes positive leading into the line's height if \a included is true; + otherwise does not include leading. - By default, leading is not included. + By default, leading is not included. - Note that negative leading is ignored, it must be handled - in the code using the text lines by letting the lines overlap. + Note that negative leading is ignored, it must be handled + in the code using the text lines by letting the lines overlap. - \sa leadingIncluded() + \sa leadingIncluded() */ void QTextLine::setLeadingIncluded(bool included) @@ -1555,20 +1625,21 @@ void QTextLine::setLeadingIncluded(bool included) } -/*! \since 4.6 +/*! + \since 4.6 - Returns true if positive leading is included into the line's height; otherwise returns false. + Returns true if positive leading is included into the line's height; + otherwise returns false. - By default, leading is not included. + By default, leading is not included. - \sa setLeadingIncluded() + \sa setLeadingIncluded() */ bool QTextLine::leadingIncluded() const { return eng->lines[i].leadingIncluded; } - /*! Returns the width of the line that is occupied by text. This is always \<= to width(), and is the minimum width that could be used @@ -1579,14 +1650,15 @@ qreal QTextLine::naturalTextWidth() const return eng->lines[i].textWidth.toReal(); } -/*! \since 4.7 - Returns the horizontal advance of the text. The advance of the text - is the distance from its position to the next position at which - text would naturally be drawn. +/*! + \since 4.7 + Returns the horizontal advance of the text. The advance of the text + is the distance from its position to the next position at which + text would naturally be drawn. - By adding the advance to the position of the text line and using this - as the position of a second text line, you will be able to position - the two lines side-by-side without gaps in-between. + By adding the advance to the position of the text line and using this + as the position of a second text line, you will be able to position + the two lines side-by-side without gaps in-between. */ qreal QTextLine::horizontalAdvance() const { @@ -1764,7 +1836,8 @@ static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &gly ++line.length; } while (pos < end && logClusters[pos] == glyphPosition); do { // calculate the textWidth for the rest of the current cluster. - line.textWidth += glyphs.advances_x[glyphPosition] * !glyphs.attributes[glyphPosition].dontPrint; + if (!glyphs.attributes[glyphPosition].dontPrint) + line.textWidth += glyphs.advances_x[glyphPosition]; ++glyphPosition; } while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart); @@ -1842,14 +1915,14 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); lbh.glyphs = eng->shapedGlyphs(¤t); + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } } const QScriptItem ¤t = eng->layoutData->items[item]; - QFontEngine *fontEngine = eng->fontEngine(current); - if (lbh.fontEngine != fontEngine) { - lbh.fontEngine = fontEngine; - lbh.minimumRightBearing = qMin(QFixed(), - QFixed::fromReal(fontEngine->minRightBearing())); - } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, @@ -2014,9 +2087,10 @@ found: eng->maxWidth += lbh.spaceData.textWidth; if (eng->option.flags() & QTextOption::IncludeTrailingSpaces) line.textWidth += lbh.spaceData.textWidth; - line.length += lbh.spaceData.length; - if (lbh.spaceData.length) + if (lbh.spaceData.length) { + line.length += lbh.spaceData.length; line.hasTrailingSpaces = true; + } line.justified = false; line.gridfitted = false; @@ -2170,6 +2244,151 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } +namespace { + struct GlyphInfo + { + GlyphInfo(const QGlyphLayout &layout, const QPointF &position, + const QTextItemInt::RenderFlags &renderFlags) + : glyphLayout(layout), itemPosition(position), flags(renderFlags) + { + } + + QGlyphLayout glyphLayout; + QPointF itemPosition; + QTextItem::RenderFlags flags; + }; +} + +/*! + \internal + + Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in + QScriptItems that overlap with the range defined by \a from and \a length. The arguments + specify characters, relative to the text in the layout. Note that it is not possible to + use this function to retrieve a subset of the glyphs in a QScriptItem. + + \since 4.8 + + \sa QTextLayout::glyphs() +*/ +QList<QGlyphs> QTextLine::glyphs(int from, int length) const +{ + const QScriptLine &line = eng->lines[i]; + + if (line.length == 0) + return QList<QGlyphs>(); + + QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; + + QTextLineItemIterator iterator(eng, i); + qreal y = line.y.toReal() + line.base().toReal(); + while (!iterator.atEnd()) { + QScriptItem &si = iterator.next(); + if (si.analysis.flags >= QScriptAnalysis::TabOrObject) + continue; + + QPointF pos(iterator.x.toReal(), y); + if (from >= 0 && length >= 0 && + (from >= si.position + eng->length(&si) || from + length <= si.position)) + continue; + + QFont font = eng->font(si); + + QTextItem::RenderFlags flags; + if (font.overline()) + flags |= QTextItem::Overline; + if (font.underline()) + flags |= QTextItem::Underline; + if (font.strikeOut()) + flags |= QTextItem::StrikeOut; + if (si.analysis.bidiLevel % 2) + flags |= QTextItem::RightToLeft; + + QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart, + iterator.glyphsEnd - iterator.glyphsStart); + + if (glyphLayout.numGlyphs > 0) { + QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + if (mainFontEngine->type() == QFontEngine::Multi) { + QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine); + int start = 0; + int end; + int which = glyphLayout.glyphs[0] >> 24; + for (end = 0; end < glyphLayout.numGlyphs; ++end) { + const int e = glyphLayout.glyphs[end] >> 24; + if (e == which) + continue; + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + start = end; + which = e; + } + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + } else { + glyphLayoutHash.insertMulti(mainFontEngine, + GlyphInfo(glyphLayout, pos, flags)); + } + } + } + + QHash<QPair<QFontEngine *, int>, QGlyphs> glyphsHash; + + QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys(); + for (int i=0; i<keys.size(); ++i) { + QFontEngine *fontEngine = keys.at(i); + + // Make a font for this particular engine + QFont font = fontEngine->createExplicitFont(); + + QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine); + for (int j=0; j<glyphLayouts.size(); ++j) { + const QPointF &pos = glyphLayouts.at(j).itemPosition; + const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout; + const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags; + + font.setOverline(flags.testFlag(QTextItem::Overline)); + font.setUnderline(flags.testFlag(QTextItem::Underline)); + font.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); + + QVarLengthArray<glyph_t> glyphsArray; + QVarLengthArray<QFixedPoint> positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector<quint32> glyphs; + QVector<QPointF> positions; + for (int i=0; i<glyphsArray.size(); ++i) { + glyphs.append(glyphsArray.at(i) & 0xffffff); + positions.append(positionsArray.at(i).toPointF() + pos); + } + + QGlyphs glyphIndexes; + glyphIndexes.setGlyphIndexes(glyphs); + glyphIndexes.setPositions(positions); + + QPair<QFontEngine *, int> key(fontEngine, int(flags)); + + if (!glyphsHash.contains(key)) + glyphsHash.insert(key, QGlyphs()); + + QGlyphs &target = glyphsHash[key]; + target += glyphIndexes; + target.setFont(font); + } + } + + return glyphsHash.values(); +} + /*! \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const @@ -2366,21 +2585,20 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR } /*! - \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const + \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const - \overload + \overload */ - /*! - Converts the cursor position \a cursorPos to the corresponding x position - inside the line, taking account of the \a edge. + Converts the cursor position \a cursorPos to the corresponding x position + inside the line, taking account of the \a edge. - If \a cursorPos is not a valid cursor position, the nearest valid - cursor position will be used instead, and cpos will be modified to - point to this valid cursor position. + If \a cursorPos is not a valid cursor position, the nearest valid + cursor position will be used instead, and cpos will be modified to + point to this valid cursor position. - \sa xToCursor() + \sa xToCursor() */ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const { @@ -2479,14 +2697,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const if(pos == l) x += si->width; } else { - int offsetInCluster = 0; - for (int i=pos-1; i >= 0; i--) { - if (logClusters[i] == glyph_pos) - offsetInCluster++; - else - break; - } - if (reverse) { int end = qMin(lineEnd, si->position + l) - si->position; int glyph_end = end == l ? si->num_glyphs : logClusters[end]; @@ -2498,17 +2708,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const for (int i = glyph_start; i < glyph_pos; i++) x += glyphs.effectiveAdvance(i); } - if (offsetInCluster > 0) { // in the case that the offset is inside a (multi-character) glyph, interpolate the position. - int clusterLength = 0; - for (int i=pos - offsetInCluster; i < line.length; i++) { - if (logClusters[i] == glyph_pos) - clusterLength++; - else - break; - } - if (clusterLength) - x+= glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; - } + x += offsetInLigature(logClusters, glyphs, pos, line.length, glyph_pos); } *cursorPos = pos + si->position; @@ -2516,12 +2716,12 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const } /*! - \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const + \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const - Converts the x-coordinate \a x, to the nearest matching cursor - position, depending on the cursor position type, \a cpos. + Converts the x-coordinate \a x, to the nearest matching cursor + position, depending on the cursor position type, \a cpos. - \sa cursorToX() + \sa cursorToX() */ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const { diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 8c93ed6..32d6d0e 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -49,6 +49,7 @@ #include <QtCore/qobject.h> #include <QtGui/qevent.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -166,6 +167,8 @@ public: qreal minimumWidth() const; qreal maximumWidth() const; + QList<QGlyphs> glyphs() const; + QTextEngine *engine() const { return d; } void setFlags(int flags); private: @@ -236,7 +239,10 @@ public: private: QTextLine(int line, QTextEngine *e) : i(line), eng(e) {} void layout_helper(int numGlyphs); + QList<QGlyphs> glyphs(int from, int length) const; + friend class QTextLayout; + friend class QTextFragment; int i; QTextEngine *eng; }; diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index d25fb05..12a8924 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1654,6 +1654,35 @@ QTextBlock::iterator &QTextBlock::iterator::operator--() than the \a other text fragment; otherwise returns false. */ +/*! + Returns the glyphs of this text fragment. The positions of the glyphs are + relative to the position of the QTextBlock's layout. + + \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextFragment::glyphs() const +{ + if (!p || !n) + return QList<QGlyphs>(); + + int pos = position(); + int len = length(); + if (len == 0) + return QList<QGlyphs>(); + + int blockNode = p->blockMap().findNode(pos); + + const QTextBlockData *blockData = p->blockMap().fragment(blockNode); + QTextLayout *layout = blockData->layout; + + QList<QGlyphs> ret; + for (int i=0; i<layout->lineCount(); ++i) { + QTextLine textLine = layout->lineAt(i); + ret += textLine.glyphs(pos, len); + } + + return ret; +} /*! Returns the position of this text fragment in the document. diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index a573a26..332458d 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -44,6 +44,7 @@ #include <QtCore/qobject.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -315,6 +316,8 @@ public: int charFormatIndex() const; QString text() const; + QList<QGlyphs> glyphs() const; + private: const QTextDocumentPrivate *p; int n; diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index af8daa5..102df4d 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -39,7 +39,9 @@ HEADERS += \ text/qzipwriter_p.h \ text/qtextodfwriter_p.h \ text/qstatictext_p.h \ - text/qstatictext.h + text/qstatictext.h \ + text/qglyphs.h \ + text/qglyphs_p.h SOURCES += \ text/qfont.cpp \ @@ -69,7 +71,8 @@ SOURCES += \ text/qcssparser.cpp \ text/qzip.cpp \ text/qtextodfwriter.cpp \ - text/qstatictext.cpp + text/qstatictext.cpp \ + text/qglyphs.cpp win32 { SOURCES += \ diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index 995d659..bd66843 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -319,7 +319,7 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const return group->d_func()->buttonList; #endif - QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent); + QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>(); if (autoExclusive) { for (int i = candidates.count() - 1; i >= 0; --i) { QAbstractButton *candidate = candidates.at(i); diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp index bc0900e..64b47b4 100644 --- a/src/gui/widgets/qcheckbox.cpp +++ b/src/gui/widgets/qcheckbox.cpp @@ -300,6 +300,15 @@ QSize QCheckBox::sizeHint() const return d->sizeHint; } + +/*! + \reimp +*/ +QSize QCheckBox::minimumSizeHint() const +{ + return sizeHint(); +} + /*! \reimp */ diff --git a/src/gui/widgets/qcheckbox.h b/src/gui/widgets/qcheckbox.h index 7b6292d..95da261 100644 --- a/src/gui/widgets/qcheckbox.h +++ b/src/gui/widgets/qcheckbox.h @@ -65,6 +65,7 @@ public: QSize sizeHint() const; + QSize minimumSizeHint() const; void setTristate(bool y = true); bool isTristate() const; diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 917a325..487d244 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu")); QVariant value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); @@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.icon = qvariant_cast<QPixmap>(variant); break; } - if (qVariantCanConvert<QBrush>(index.data(Qt::BackgroundRole))) { + if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) { menuOption.palette.setBrush(QPalette::All, QPalette::Background, qvariant_cast<QBrush>(index.data(Qt::BackgroundRole))); } @@ -369,6 +369,7 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent) if (timerEvent->timerId() == adjustSizeTimer.timerId()) { adjustSizeTimer.stop(); if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) { + combo->updateGeometry(); combo->adjustSize(); combo->update(); } @@ -1298,7 +1299,7 @@ QComboBox::~QComboBox() By default, this property has a value of 10. \note This property is ignored for non-editable comboboxes in styles that returns - false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. + true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. */ int QComboBox::maxVisibleItems() const { @@ -2008,11 +2009,18 @@ void QComboBox::setCurrentIndex(int index) void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) { Q_Q(QComboBox); - bool indexChanged = (mi != currentIndex); + + QModelIndex normalized; + if (mi.column() != modelColumn) + normalized = model->index(mi.row(), modelColumn, mi.parent()); + if (!normalized.isValid()) + normalized = mi; // Fallback to passed index. + + bool indexChanged = (normalized != currentIndex); if (indexChanged) - currentIndex = QPersistentModelIndex(mi); + currentIndex = QPersistentModelIndex(normalized); if (lineEdit) { - QString newText = q->itemText(currentIndex.row()); + QString newText = q->itemText(normalized.row()); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h index fb9af9f..81a4389 100644 --- a/src/gui/widgets/qcombobox.h +++ b/src/gui/widgets/qcombobox.h @@ -68,7 +68,7 @@ class Q_GUI_EXPORT QComboBox : public QWidget Q_PROPERTY(bool editable READ isEditable WRITE setEditable) Q_PROPERTY(int count READ count) Q_PROPERTY(QString currentText READ currentText) - Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged USER true) Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems) Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) Q_PROPERTY(InsertPolicy insertPolicy READ insertPolicy WRITE setInsertPolicy) diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index 29a628c..c0727ed 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -337,7 +337,7 @@ private: QComboBox *mCombo; }; -class QComboBoxPrivate : public QWidgetPrivate +class Q_AUTOTEST_EXPORT QComboBoxPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QComboBox) public: diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp index 7a61dc7..3bc6412 100644 --- a/src/gui/widgets/qdatetimeedit.cpp +++ b/src/gui/widgets/qdatetimeedit.cpp @@ -890,7 +890,13 @@ void QDateTimeEdit::setDisplayFormat(const QString &format) const bool dateShown = (d->sections & DateSections_Mask); Q_ASSERT(dateShown || timeShown); if (timeShown && !dateShown) { + QTime time = d->value.toTime(); setDateRange(d->value.toDate(), d->value.toDate()); + if (d->minimum.toTime() >= d->maximum.toTime()) { + setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); + // if the time range became invalid during the adjustment, the time would have been reset + setTime(time); + } } else if (dateShown && !timeShown) { setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); d->value = QDateTime(d->value.toDate(), QTime(), d->spec); @@ -1668,6 +1674,15 @@ void QDateTimeEditPrivate::updateTimeSpec() minimum = minimum.toDateTime().toTimeSpec(spec); maximum = maximum.toDateTime().toTimeSpec(spec); value = value.toDateTime().toTimeSpec(spec); + + // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range) + const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask); + if (!dateShown) { + if (minimum.toTime() >= maximum.toTime()){ + minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec); + maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec); + } + } } void QDateTimeEditPrivate::updateEdit() diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 732dbc9..9aea32a 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -1229,7 +1229,7 @@ bool QDialogButtonBox::event(QEvent *event) break; } - foreach (QPushButton *pb, qFindChildren<QPushButton *>(dialog ? dialog : this)) { + foreach (QPushButton *pb, (dialog ? dialog : this)->findChildren<QPushButton *>()) { if (pb->isDefault() && pb != firstAcceptButton) { hasDefault = true; break; diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index bdbd0b0..f5393a9 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -1071,7 +1071,7 @@ void QLabel::paintEvent(QPaintEvent *) else #endif if (d->isTextLabel) { - QRectF lr = d->layoutRect(); + QRectF lr = d->layoutRect().toAlignedRect(); QStyleOption opt; opt.initFrom(this); #ifndef QT_NO_STYLE_STYLESHEET diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h index 94e0dbe..667562b 100644 --- a/src/gui/widgets/qlineedit.h +++ b/src/gui/widgets/qlineedit.h @@ -283,6 +283,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool)) #endif Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged()) + Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &)) }; #endif // QT_NO_LINEEDIT diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp index 468c111..d705fa8 100644 --- a/src/gui/widgets/qlineedit_p.cpp +++ b/src/gui/widgets/qlineedit_p.cpp @@ -59,6 +59,13 @@ QT_BEGIN_NAMESPACE const int QLineEditPrivate::verticalMargin(1); const int QLineEditPrivate::horizontalMargin(2); +QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const +{ + QRect cr = adjustedContentsRect(); + int cix = cr.x() - hscroll + horizontalMargin; + return rect.translated(QPoint(cix, vscroll)); +} + int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const { QRect cr = adjustedContentsRect(); @@ -68,11 +75,7 @@ int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const QRect QLineEditPrivate::cursorRect() const { - QRect cr = adjustedContentsRect(); - int cix = cr.x() - hscroll + horizontalMargin; - QRect crect = control->cursorRect(); - crect.moveTo(crect.topLeft() + QPoint(cix, vscroll)); - return crect; + return adjustedControlRect(control->cursorRect()); } #ifndef QT_NO_COMPLETER @@ -141,6 +144,11 @@ void QLineEditPrivate::_q_selectionChanged() emit q->selectionChanged(); } +void QLineEditPrivate::_q_updateNeeded(const QRect &rect) +{ + q_func()->update(adjustedControlRect(rect)); +} + void QLineEditPrivate::init(const QString& txt) { Q_Q(QLineEdit); @@ -176,7 +184,7 @@ void QLineEditPrivate::init(const QString& txt) q, SLOT(update())); QObject::connect(control, SIGNAL(updateNeeded(QRect)), - q, SLOT(update())); + q, SLOT(_q_updateNeeded(QRect))); QStyleOptionFrameV2 opt; q->initStyleOption(&opt); @@ -216,9 +224,8 @@ void QLineEditPrivate::setCursorVisible(bool visible) if ((bool)cursorVisible == visible) return; cursorVisible = visible; - QRect r = cursorRect(); if (control->inputMask().isEmpty()) - q->update(r); + q->update(cursorRect()); else q->update(); } diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 7a24cb3..b9f9c0b 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -94,6 +94,8 @@ public: #endif void init(const QString&); + QRect adjustedControlRect(const QRect &) const; + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; QRect cursorRect() const; void setCursorVisible(bool visible); @@ -129,6 +131,7 @@ public: void _q_editFocusChange(bool); #endif void _q_selectionChanged(); + void _q_updateNeeded(const QRect &); #ifndef QT_NO_COMPLETER void _q_completionHighlighted(QString); #endif diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 44483ea..0378d2d 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1573,7 +1573,7 @@ QMenu *QMainWindow::createPopupMenu() Q_D(QMainWindow); QMenu *menu = 0; #ifndef QT_NO_DOCKWIDGET - QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this); + QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>(); if (dockwidgets.size()) { menu = new QMenu(this); for (int i = 0; i < dockwidgets.size(); ++i) { @@ -1587,7 +1587,7 @@ QMenu *QMainWindow::createPopupMenu() } #endif // QT_NO_DOCKWIDGET #ifndef QT_NO_TOOLBAR - QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this); + QList<QToolBar *> toolbars = findChildren<QToolBar *>(); if (toolbars.size()) { if (!menu) menu = new QMenu(this); diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp index 62d297e..3f4cdc3 100644 --- a/src/gui/widgets/qmdisubwindow.cpp +++ b/src/gui/widgets/qmdisubwindow.cpp @@ -2203,7 +2203,7 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip) void QMdiSubWindowPrivate::setSizeGripVisible(bool visible) const { // See if we can find any size grips - QList<QSizeGrip *> sizeGrips = qFindChildren<QSizeGrip *>(q_func()); + QList<QSizeGrip *> sizeGrips = q_func()->findChildren<QSizeGrip *>(); foreach (QSizeGrip *grip, sizeGrips) grip->setVisible(visible); } @@ -2319,7 +2319,7 @@ void QMdiSubWindow::setWidget(QWidget *widget) widget->setParent(this); #ifndef QT_NO_SIZEGRIP - QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(widget); + QSizeGrip *sizeGrip = widget->findChild<QSizeGrip *>(); if (sizeGrip) sizeGrip->installEventFilter(this); if (d->sizeGrip) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 4bea6de..245657a 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -2804,7 +2804,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) if (d->sloppyRegion.contains(e->pos())) { d->sloppyAction = action; QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6); - } else { + } else if (action != d->currentAction) { d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); } } diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index aaa113b..60023a8 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1254,15 +1254,11 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) { quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL)); - extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp - QChar keyEquiv = qt_macSymbolForQtKey(accel_key); - if (keyEquiv.isNull()) { - if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15) - keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey; - else - keyEquiv = unichar(QChar(accel_key).toLower().unicode()); - } - return [NSString stringWithCharacters:&keyEquiv.unicode() length:1]; + extern QChar qtKey2CocoaKey(Qt::Key key); + QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key)); + if (cocoa_key.isNull()) + cocoa_key = QChar(accel_key).toLower().unicode(); + return [NSString stringWithCharacters:&cocoa_key.unicode() length:1]; } // return the cocoa modifier mask for the QKeySequence (currently only looks at the first one). @@ -2052,8 +2048,7 @@ bool QMenuBar::macUpdateMenuBar() { #ifdef QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; - if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar))) - return QMenuBarPrivate::macUpdateMenuBarImmediatly(); + qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)); return true; #else return QMenuBarPrivate::macUpdateMenuBarImmediatly(); diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index ab2bdea..c643a1e 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -264,7 +264,8 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) // However if we don't have any items, we still need the item array. Otherwise // menupane will crash. That's why we create item array here manually, and // AddMenuItemL will then use the existing array. - CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray); + CEikMenuPane::CItemArray* itemArray = new CEikMenuPane::CItemArray; + Q_CHECK_PTR(itemArray); menuPane->SetItemArray(itemArray); menuPane->SetItemArrayOwnedExternally(EFalse); diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index e088db6..15d0116 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -113,8 +113,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary aygLib(QLatin1String("aygshell")); - if (!aygLib.load()) - return; ptrCreateMenuBar = (AygCreateMenuBar) aygLib.resolve("SHCreateMenuBar"); ptrEnableSoftKey = (AygEnableSoftKey) aygLib.resolve("SHEnableSoftkey"); } diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp index 20b6c720..56bd709 100644 --- a/src/gui/widgets/qradiobutton.cpp +++ b/src/gui/widgets/qradiobutton.cpp @@ -207,6 +207,14 @@ QSize QRadioButton::sizeHint() const /*! \reimp */ +QSize QRadioButton::minimumSizeHint() const +{ + return sizeHint(); +} + +/*! + \reimp +*/ bool QRadioButton::hitButton(const QPoint &pos) const { QStyleOptionButton opt; diff --git a/src/gui/widgets/qradiobutton.h b/src/gui/widgets/qradiobutton.h index 887b747..b7031e2 100644 --- a/src/gui/widgets/qradiobutton.h +++ b/src/gui/widgets/qradiobutton.h @@ -62,6 +62,7 @@ public: explicit QRadioButton(const QString &text, QWidget *parent=0); QSize sizeHint() const; + QSize minimumSizeHint() const; protected: bool event(QEvent *e); diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp index c9d613a..b5b611c 100644 --- a/src/gui/widgets/qsizegrip.cpp +++ b/src/gui/widgets/qsizegrip.cpp @@ -78,15 +78,6 @@ static QWidget *qt_sizegrip_topLevelWidget(QWidget* w) return w; } -static inline bool hasHeightForWidth(QWidget *widget) -{ - if (!widget) - return false; - if (QLayout *layout = widget->layout()) - return layout->hasHeightForWidth(); - return widget->sizePolicy().hasHeightForWidth(); -} - class QSizeGripPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QSizeGrip) @@ -318,7 +309,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) #ifdef Q_WS_X11 // Use a native X11 sizegrip for "real" top-level windows if supported. if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE); @@ -340,7 +331,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) } #endif // Q_WS_X11 #ifdef Q_WS_WIN - if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { uint orientation = 0; if (d->atBottom()) orientation = d->atLeft() ? SZ_SIZEBOTTOMLEFT : SZ_SIZEBOTTOMRIGHT; @@ -429,12 +420,12 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e) #ifdef Q_WS_X11 if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) + && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) return; #endif #ifdef Q_WS_WIN if (tlw->isWindow() && GetSystemMenu(tlw->winId(), FALSE) != 0 && internalWinId() - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { MSG msg; while(PeekMessage(&msg, winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)); return; diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index 2d871d0..10ce144 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -697,6 +697,9 @@ void QDoubleSpinBox::setSuffix(const QString &suffix) d->suffix = suffix; d->updateEdit(); + + d->cachedSizeHint = QSize(); + updateGeometry(); } /*! diff --git a/src/gui/widgets/qsplashscreen.cpp b/src/gui/widgets/qsplashscreen.cpp index 8be0cf8..2b6bfeb 100644 --- a/src/gui/widgets/qsplashscreen.cpp +++ b/src/gui/widgets/qsplashscreen.cpp @@ -64,7 +64,6 @@ public: int currAlign; inline QSplashScreenPrivate(); - void drawContents(); }; /*! @@ -121,10 +120,9 @@ public: perhaps Qt::WindowStaysOnTopHint. */ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) - : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | f) + : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | Qt::FramelessWindowHint | f) { - d_func()->pixmap = pixmap; - setPixmap(d_func()->pixmap); // Does an implicit repaint + setPixmap(pixmap); // Does an implicit repaint } /*! @@ -165,7 +163,6 @@ void QSplashScreen::mousePressEvent(QMouseEvent *) */ void QSplashScreen::repaint() { - d_func()->drawContents(); QWidget::repaint(); QApplication::flush(); } @@ -234,23 +231,13 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap) { Q_D(QSplashScreen); - if (pixmap.hasAlpha()) { - QPixmap opaque(pixmap.size()); - QPainter p(&opaque); - p.fillRect(0, 0, pixmap.width(), pixmap.height(), palette().background()); - p.drawPixmap(0, 0, pixmap); - p.end(); - d->pixmap = opaque; - } else { - d->pixmap = pixmap; - } + d->pixmap = pixmap; + setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha()); - QRect r(0, 0, d->pixmap.size().width(), d->pixmap.size().height()); - resize(d->pixmap.size()); + QRect r(QPoint(), d->pixmap.size()); + resize(r.size()); move(QApplication::desktop()->screenGeometry().center() - r.center()); - if (!isVisible()) - d->drawContents(); - else + if (isVisible()) repaint(); } @@ -264,23 +251,6 @@ const QPixmap QSplashScreen::pixmap() const } /*! - \internal -*/ -void QSplashScreenPrivate::drawContents() -{ - Q_Q(QSplashScreen); - QPixmap textPix = pixmap; - if (!textPix.isNull()) { - QPainter painter(&textPix); - painter.initFrom(q); - q->drawContents(&painter); - QPalette p = q->palette(); - p.setBrush(q->backgroundRole(), QBrush(textPix)); - q->setPalette(p); - } -} - -/*! \internal */ inline QSplashScreenPrivate::QSplashScreenPrivate() : currAlign(Qt::AlignLeft) @@ -297,8 +267,7 @@ void QSplashScreen::drawContents(QPainter *painter) { Q_D(QSplashScreen); painter->setPen(d->currColor); - QRect r = rect(); - r.setRect(r.x() + 5, r.y() + 5, r.width() - 10, r.height() - 10); + QRect r = rect().adjusted(5, 5, -5, -5); if (Qt::mightBeRichText(d->currStatus)) { QTextDocument doc; #ifdef QT_NO_TEXTHTMLPARSER @@ -339,6 +308,13 @@ void QSplashScreen::drawContents(QPainter *painter) /*! \reimp */ bool QSplashScreen::event(QEvent *e) { + if (e->type() == QEvent::Paint) { + Q_D(QSplashScreen); + QPainter painter(this); + if (!d->pixmap.isNull()) + painter.drawPixmap(QPoint(), d->pixmap); + drawContents(&painter); + } return QWidget::event(e); } diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp index de8d3e6..57b43b5 100644 --- a/src/gui/widgets/qstackedwidget.cpp +++ b/src/gui/widgets/qstackedwidget.cpp @@ -49,12 +49,54 @@ QT_BEGIN_NAMESPACE +/** + QStackedLayout does not support height for width (simply because it does not reimplement + heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking + binary compatibility. (QLayout is subject to multiple inheritance). + However, we can fix QStackedWidget by simply using a modified version of QStackedLayout + that reimplements the hfw-related functions: + */ +class QStackedLayoutHFW : public QStackedLayout +{ +public: + QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {} + bool hasHeightForWidth() const; + int heightForWidth(int width) const; +}; + +bool QStackedLayoutHFW::hasHeightForWidth() const +{ + const int n = count(); + + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + if (item->hasHeightForWidth()) + return true; + } + } + return false; +} + +int QStackedLayoutHFW::heightForWidth(int width) const +{ + const int n = count(); + + int hfw = 0; + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + hfw = qMax(hfw, item->heightForWidth(width)); + } + } + return hfw; +} + + class QStackedWidgetPrivate : public QFramePrivate { Q_DECLARE_PUBLIC(QStackedWidget) public: QStackedWidgetPrivate():layout(0){} - QStackedLayout *layout; + QStackedLayoutHFW *layout; bool blockChildAdd; }; @@ -138,7 +180,7 @@ QStackedWidget::QStackedWidget(QWidget *parent) : QFrame(*new QStackedWidgetPrivate, parent) { Q_D(QStackedWidget); - d->layout = new QStackedLayout(this); + d->layout = new QStackedLayoutHFW(this); connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int))); connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int))); } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index bbc7e5d..8a470ee 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1292,6 +1292,8 @@ QSize QTabBar::sizeHint() const QSize QTabBar::minimumSizeHint() const { Q_D(const QTabBar); + if (d->layoutDirty) + const_cast<QTabBarPrivate*>(d)->layoutTabs(); if (!d->useScrollButtons) { QRect r; for (int i = 0; i < d->tabList.count(); ++i) @@ -1304,22 +1306,23 @@ QSize QTabBar::minimumSizeHint() const return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height()); } +// Compute the most-elided possible text, for minimumSizeHint static QString computeElidedText(Qt::TextElideMode mode, const QString &text) { - if (text.length() <= 7) + if (text.length() <= 3) return text; static const QLatin1String Ellipses("..."); QString ret; switch (mode) { case Qt::ElideRight: - ret = text.left(4) + Ellipses; + ret = text.left(2) + Ellipses; break; case Qt::ElideMiddle: - ret = text.left(2) + Ellipses + text.right(2); + ret = text.left(1) + Ellipses + text.right(1); break; case Qt::ElideLeft: - ret = Ellipses + text.right(4); + ret = Ellipses + text.right(2); break; case Qt::ElideNone: ret = text; @@ -1966,7 +1969,7 @@ void QTabBar::keyPressEvent(QKeyEvent *event) event->ignore(); return; } - int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; + int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; d->setCurrentNextEnabledIndex(offset); } diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp index 4a61935..82dfdef 100644 --- a/src/gui/widgets/qtabwidget.cpp +++ b/src/gui/widgets/qtabwidget.cpp @@ -195,6 +195,7 @@ public: void _q_removeTab(int); void _q_tabMoved(int from, int to); void init(); + bool hasHeightForWidth() const; QTabBar *tabs; QStackedWidget *stack; @@ -246,6 +247,15 @@ void QTabWidgetPrivate::init() } +bool QTabWidgetPrivate::hasHeightForWidth() const +{ + bool has = size_policy.hasHeightForWidth(); + if (!has && stack) + has = qt_widget_private(stack)->hasHeightForWidth(); + return has; +} + + /*! Initialize \a option with the values from this QTabWidget. This method is useful for subclasses when they need a QStyleOptionTabWidgetFrame, but don't want to fill @@ -816,8 +826,8 @@ QSize QTabWidget::sizeHint() const { Q_D(const QTabWidget); QSize lc(0, 0), rc(0, 0); - QStyleOption opt(0); - opt.init(this); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.state = QStyle::State_None; if (d->leftCornerWidget) @@ -865,14 +875,58 @@ QSize QTabWidget::minimumSizeHint() const QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t); - QStyleOption opt(0); - opt.rect = rect(); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.palette = palette(); opt.state = QStyle::State_None; return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this) .expandedTo(QApplication::globalStrut()); } +/* + \reimp +*/ +int QTabWidget::heightForWidth(int width) const +{ + Q_D(const QTabWidget); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); + opt.state = QStyle::State_None; + + QSize zero(0,0); + const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this) + .expandedTo(QApplication::globalStrut()); + + QSize lc(0, 0), rc(0, 0); + if (d->leftCornerWidget) + lc = d->leftCornerWidget->sizeHint(); + if(d->rightCornerWidget) + rc = d->rightCornerWidget->sizeHint(); + if (!d->dirty) { + QTabWidget *that = (QTabWidget*)this; + that->setUpLayout(true); + } + QSize t(d->tabs->sizeHint()); + + if(usesScrollButtons()) + t = t.boundedTo(QSize(200,200)); + else + t = t.boundedTo(QApplication::desktop()->size()); + + const bool tabIsHorizontal = (d->pos == North || d->pos == South); + const int contentsWidth = width - padding.width(); + int stackWidth = contentsWidth; + if (!tabIsHorizontal) + stackWidth -= qMax(t.width(), qMax(lc.width(), rc.width())); + + int stackHeight = d->stack->heightForWidth(stackWidth); + QSize s(stackWidth, stackHeight); + + QSize contentSize = basicSize(tabIsHorizontal, lc, rc, s, t); + return (contentSize + padding).expandedTo(QApplication::globalStrut()).height(); +} + + /*! \reimp */ diff --git a/src/gui/widgets/qtabwidget.h b/src/gui/widgets/qtabwidget.h index 68200c8..ee50655 100644 --- a/src/gui/widgets/qtabwidget.h +++ b/src/gui/widgets/qtabwidget.h @@ -129,6 +129,7 @@ public: QSize sizeHint() const; QSize minimumSizeHint() const; + int heightForWidth(int width) const; void setCornerWidget(QWidget * w, Qt::Corner corner = Qt::TopRightCorner); QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const; diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 7180c4d..5cf67a5 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -2923,7 +2923,7 @@ void QWorkspaceChild::setActive(bool b) iconw->setActive(act); update(); - QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget); + QList<QWidget*> wl = childWidget->findChildren<QWidget*>(); if (act) { for (int i = 0; i < wl.size(); ++i) { QWidget *w = wl.at(i); diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp index ecd03e5..19f3b3c 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp @@ -127,7 +127,7 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const } } - delete streams; + delete[] streams; } } @@ -201,7 +201,7 @@ QList<int> QAudioDeviceInfoInternal::frequencyList() rc << vr[i].mMaximum; } - delete vr; + delete[] vr; } } @@ -345,7 +345,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) } } - delete audioDevices; + delete[] audioDevices; } } diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp index 3afbdc9..3ec40e8 100644 --- a/src/multimedia/video/qvideosurfaceformat.cpp +++ b/src/multimedia/video/qvideosurfaceformat.cpp @@ -502,11 +502,11 @@ QList<QByteArray> QVideoSurfaceFormat::propertyNames() const QVariant QVideoSurfaceFormat::property(const char *name) const { if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "pixelFormat") == 0) { - return qVariantFromValue(d->pixelFormat); + return QVariant::fromValue(d->pixelFormat); } else if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "frameSize") == 0) { return d->frameSize; } else if (qstrcmp(name, "frameWidth") == 0) { @@ -516,15 +516,15 @@ QVariant QVideoSurfaceFormat::property(const char *name) const } else if (qstrcmp(name, "viewport") == 0) { return d->viewport; } else if (qstrcmp(name, "scanLineDirection") == 0) { - return qVariantFromValue(d->scanLineDirection); + return QVariant::fromValue(d->scanLineDirection); } else if (qstrcmp(name, "frameRate") == 0) { - return qVariantFromValue(d->frameRate); + return QVariant::fromValue(d->frameRate); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - return qVariantFromValue(d->pixelAspectRatio); + return QVariant::fromValue(d->pixelAspectRatio); } else if (qstrcmp(name, "sizeHint") == 0) { return sizeHint(); } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - return qVariantFromValue(d->ycbcrColorSpace); + return QVariant::fromValue(d->ycbcrColorSpace); } else { int id = 0; for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {} @@ -546,7 +546,7 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "pixelFormat") == 0) { // read only. } else if (qstrcmp(name, "frameSize") == 0) { - if (qVariantCanConvert<QSize>(value)) { + if (value.canConvert<QSize>()) { d->frameSize = qvariant_cast<QSize>(value); d->viewport = QRect(QPoint(0, 0), d->frameSize); } @@ -555,21 +555,21 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "frameHeight") == 0) { // read only. } else if (qstrcmp(name, "viewport") == 0) { - if (qVariantCanConvert<QRect>(value)) + if (value.canConvert<QRect>()) d->viewport = qvariant_cast<QRect>(value); } else if (qstrcmp(name, "scanLineDirection") == 0) { - if (qVariantCanConvert<Direction>(value)) + if (value.canConvert<Direction>()) d->scanLineDirection = qvariant_cast<Direction>(value); } else if (qstrcmp(name, "frameRate") == 0) { - if (qVariantCanConvert<qreal>(value)) + if (value.canConvert<qreal>()) d->frameRate = qvariant_cast<qreal>(value); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - if (qVariantCanConvert<QSize>(value)) + if (value.canConvert<QSize>()) d->pixelAspectRatio = qvariant_cast<QSize>(value); } else if (qstrcmp(name, "sizeHint") == 0) { // read only. } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - if (qVariantCanConvert<YCbCrColorSpace>(value)) + if (value.canConvert<YCbCrColorSpace>()) d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value); } else { int id = 0; diff --git a/src/network/access/qfilenetworkreply.cpp b/src/network/access/qfilenetworkreply.cpp index 4ac9a8c..8c0fd17 100644 --- a/src/network/access/qfilenetworkreply.cpp +++ b/src/network/access/qfilenetworkreply.cpp @@ -68,10 +68,9 @@ QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req setRequest(req); setUrl(req.url()); setOperation(op); + setFinished(true); QNetworkReply::open(QIODevice::ReadOnly); - qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); - QFileNetworkReplyPrivate *d = (QFileNetworkReplyPrivate*) d_func(); QUrl url = req.url(); @@ -141,12 +140,6 @@ QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } - -bool QFileNetworkReplyPrivate::isFinished() const -{ - return true; -} - void QFileNetworkReply::close() { Q_D(QFileNetworkReply); diff --git a/src/network/access/qfilenetworkreply_p.h b/src/network/access/qfilenetworkreply_p.h index 710ec9f..227c775 100644 --- a/src/network/access/qfilenetworkreply_p.h +++ b/src/network/access/qfilenetworkreply_p.h @@ -92,8 +92,6 @@ public: qint64 fileSize; qint64 filePos; - virtual bool isFinished() const; - Q_DECLARE_PUBLIC(QFileNetworkReply) }; diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index ae4d257..95ccb77 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -117,6 +117,7 @@ void QHttpNetworkConnectionPrivate::init() { for (int i = 0; i < channelCount; i++) { channels[i].setConnection(this->q_func()); + channels[i].ssl = encrypt; channels[i].init(); } } @@ -530,33 +531,35 @@ void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) return; - - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing highPriorityQueue, size=" << highPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); int lengthBefore; while (!highPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(highPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything, now do the low prio queue } - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing lowPriorityQueue, size=" << lowPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); while (!lowPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(lowPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything } + channels[i].pipelineFlush(); } // returns true when the processing of a queue has been done diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 6437f6f..e39f9ed 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) + , ssl(false) , state(IdleState) , reply(0) , written(0) @@ -90,11 +91,8 @@ void QHttpNetworkConnectionChannel::init() #else socket = new QTcpSocket; #endif - - // limit the socket read buffer size. we will read everything into - // the QHttpNetworkReply anyway, so let's grow only that and not - // here and there. - socket->setReadBufferSize(64*1024); + // Set by QNAM anyway, but let's be safe here + socket->setProxy(QNetworkProxy::NoProxy); QObject::connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_bytesWritten(qint64)), @@ -164,11 +162,12 @@ bool QHttpNetworkConnectionChannel::sendRequest() written = 0; // excluding the header bytesTotal = 0; - reply->d_func()->clear(); - reply->d_func()->connection = connection; - reply->d_func()->connectionChannel = this; - reply->d_func()->autoDecompress = request.d->autoDecompress; - reply->d_func()->pipeliningUsed = false; + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + replyPrivate->clear(); + replyPrivate->connection = connection; + replyPrivate->connectionChannel = this; + replyPrivate->autoDecompress = request.d->autoDecompress; + replyPrivate->pipeliningUsed = false; pendingEncrypt = false; // if the url contains authentication parameters, use the new ones @@ -328,7 +327,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - qint64 bytes = 0; QAbstractSocket::SocketState socketState = socket->state(); // connection might be closed to signal the end of data @@ -349,12 +347,14 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } // read loop for the response - while (socket->bytesAvailable()) { + qint64 bytes = 0; + qint64 lastBytes = bytes; + do { + lastBytes = bytes; + QHttpNetworkReplyPrivate::ReplyState state = reply->d_func()->state; switch (state) { case QHttpNetworkReplyPrivate::NothingDoneState: { - // only eat whitespace on the first call - eatWhitespace(); state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; // fallthrough } @@ -378,6 +378,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } bytes += headerBytes; + // If headers were parsed successfully now it is the ReadingDataState if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { // remove the Content-Length from header @@ -392,6 +393,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } if (replyPrivate->shouldEmitSignals()) emit reply->headerChanged(); + // After headerChanged had been emitted + // we can suddenly have a replyPrivate->userProvidedDownloadBuffer + // this is handled in the ReadingDataState however + if (!replyPrivate->expectContent()) { replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); @@ -412,22 +417,27 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress - && replyPrivate->bodyLength > 0) { - // bulk files like images should fulfill these properties and - // we can therefore save on memory copying - bytes = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); - replyPrivate->totalProgress += bytes; + if (replyPrivate->userProvidedDownloadBuffer) { + // the user provided a direct buffer where we should put all our data in. + // this only works when we can tell the user the content length and he/she can allocate + // the buffer in that size. + // note that this call will read only from the still buffered data + qint64 haveRead = replyPrivate->readBodyVeryFast(socket, replyPrivate->userProvidedDownloadBuffer + replyPrivate->totalProgress); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; + + // the user will get notified of it via progress signal + emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); + } else if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress + && replyPrivate->bodyLength > 0) { + // bulk files like images should fulfill these properties and + // we can therefore save on memory copying + qint64 haveRead = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } else @@ -435,8 +445,9 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // use the traditional slower reading (for compressed encoding, chunked encoding, // no content-length etc) QByteDataBuffer byteDatas; - bytes = replyPrivate->readBody(socket, &byteDatas); - if (bytes) { + qint64 haveRead = replyPrivate->readBody(socket, &byteDatas); + if (haveRead) { + bytes += haveRead; if (replyPrivate->autoDecompress) replyPrivate->appendCompressedReplyData(byteDatas); else @@ -445,17 +456,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() if (!replyPrivate->autoDecompress) { replyPrivate->totalProgress += bytes; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), the byteDatas list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } #ifndef QT_NO_COMPRESS @@ -477,7 +481,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() default: break; } - } + } while (bytes != lastBytes && reply); } // called when unexpectedly reading a -1 or when data is expected but socket is closed @@ -520,7 +524,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection() if (socketState != QAbstractSocket::ConnectedState) { // connect to the host if not already connected. state = QHttpNetworkConnectionChannel::ConnectingState; - pendingEncrypt = connection->d_func()->encrypt; + pendingEncrypt = ssl; // reset state pipeliningSupported = PipeliningSupportUnknown; @@ -543,23 +547,43 @@ bool QHttpNetworkConnectionChannel::ensureConnection() #ifndef QT_NO_NETWORKPROXY // HTTPS always use transparent proxy. - if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !connection->d_func()->encrypt) { + if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl) { connectHost = connection->d_func()->networkProxy.hostName(); connectPort = connection->d_func()->networkProxy.port(); } #endif - if (connection->d_func()->encrypt) { + if (ssl) { #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); sslSocket->connectToHostEncrypted(connectHost, connectPort); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); sslSocket->ignoreSslErrors(ignoreSslErrorsList); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); #else connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError); #endif } else { - socket->connectToHost(connectHost, connectPort); + // In case of no proxy we can use the Unbuffered QTcpSocket + if (connection->d_func()->networkProxy.type() == QNetworkProxy::NoProxy + && connection->cacheProxy().type() == QNetworkProxy::NoProxy + && connection->transparentProxy().type() == QNetworkProxy::NoProxy) { + socket->connectToHost(connectHost, connectPort, QIODevice::ReadWrite | QIODevice::Unbuffered); + // For an Unbuffered QTcpSocket, the read buffer size has a special meaning. + socket->setReadBufferSize(1*1024); + + } else { + socket->connectToHost(connectHost, connectPort); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); + } } return false; } @@ -589,18 +613,10 @@ bool QHttpNetworkConnectionChannel::expand(bool dataComplete) reply->d_func()->totalProgress += inflated.size(); reply->d_func()->appendUncompressedReplyData(inflated); if (reply->d_func()->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), inflated must be cleared, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; - } } } else { @@ -678,10 +694,15 @@ void QHttpNetworkConnectionChannel::allDone() // this was wrong, allDone gets called from that function anyway. } } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) { - eatWhitespace(); // this is weird. we had nothing pipelined but still bytes available. better close it. - if (socket->bytesAvailable() > 0) - close(); + //if (socket->bytesAvailable() > 0) + // close(); + // + // FIXME + // We do not close it anymore now, but should introduce this again after having fixed + // the chunked decoder in QHttpNetworkReply to read the whitespace after the last chunk. + // (Currently this is worked around by readStatus in the QHttpNetworkReply ignoring + // leading whitespace. QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else if (alreadyPipelinedRequests.isEmpty()) { if (qobject_cast<QHttpNetworkConnection*>(connection)) @@ -728,30 +749,6 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } -void QHttpNetworkConnectionChannel::eatWhitespace() -{ - char c; - do { - qint64 ret = socket->peek(&c, 1); - - // nothing read, fine. - if (ret == 0) - return; - - // EOF from socket? - if (ret == -1) - return; // FIXME, we need to stop processing. however the next stuff done will also do that. - - // read all whitespace and line endings - if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) { - socket->read(&c, 1); - continue; - } else { - break; - } - } while(true); -} - void QHttpNetworkConnectionChannel::handleStatus() { Q_ASSERT(socket); @@ -813,7 +810,7 @@ bool QHttpNetworkConnectionChannel::resetUploadData() } -void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) +void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { // this is only called for simple GET @@ -826,16 +823,32 @@ void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) reply->d_func()->pipeliningUsed = true; #ifndef QT_NO_NETWORKPROXY - QByteArray header = QHttpNetworkRequestPrivate::header(request, - (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy)); + pipeline.append(QHttpNetworkRequestPrivate::header(request, + (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy))); #else - QByteArray header = QHttpNetworkRequestPrivate::header(request, false); + pipeline.append(QHttpNetworkRequestPrivate::header(request, false)); #endif - socket->write(header); alreadyPipelinedRequests.append(pair); + + // pipelineFlush() needs to be called at some point afterwards } +void QHttpNetworkConnectionChannel::pipelineFlush() +{ + if (pipeline.isEmpty()) + return; + + // The goal of this is so that we have everything in one TCP packet. + // For the Unbuffered QTcpSocket this is manually needed, the buffered + // QTcpSocket does it automatically. + // Also, sometimes the OS does it for us (Nagle's algorithm) but that + // happens only sometimes. + socket->write(pipeline); + pipeline.clear(); +} + + void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() { requeueCurrentlyPipelinedRequests(); @@ -868,6 +881,19 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const //private slots void QHttpNetworkConnectionChannel::_q_readyRead() { + // We got a readyRead but no bytes are available.. + // This happens for the Unbuffered QTcpSocket + // Also check if socket is in ConnectedState since + // this function may also be invoked via the event loop. + if (socket->state() == QAbstractSocket::ConnectedState && socket->bytesAvailable() == 0) { + char c; + qint64 ret = socket->peek(&c, 1); + if (ret < 0) { + socket->disconnectFromHost(); + return; + } + } + if (isSocketWaiting() || isSocketReading()) { state = QHttpNetworkConnectionChannel::ReadingState; if (reply) diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 41a896d..4f3a65c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -99,6 +99,7 @@ public: BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState) }; QAbstractSocket *socket; + bool ssl; ChannelState state; QHttpNetworkRequest request; // current request QHttpNetworkReply *reply; // current reply for this request @@ -125,7 +126,11 @@ public: }; PipeliningSupport pipeliningSupported; QList<HttpMessagePair> alreadyPipelinedRequests; - + QByteArray pipeline; // temporary buffer that gets sent to socket in pipelineFlush + void pipelineInto(HttpMessagePair &pair); + void pipelineFlush(); + void requeueCurrentlyPipelinedRequests(); + void detectPipeliningSupport(); QHttpNetworkConnectionChannel(); @@ -145,15 +150,9 @@ public: bool resetUploadData(); // return true if resetting worked or there is no upload data - void pipelineInto(HttpMessagePair &pair); - void requeueCurrentlyPipelinedRequests(); - void detectPipeliningSupport(); - void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); - void eatWhitespace(); - bool isSocketBusy() const; bool isSocketWriting() const; bool isSocketWaiting() const; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 108ba8a..1c55482 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -119,6 +119,7 @@ void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request) { Q_D(QHttpNetworkReply); d->request = request; + d->ssl = request.isSsl(); } int QHttpNetworkReply::statusCode() const @@ -195,6 +196,25 @@ void QHttpNetworkReply::setDownstreamLimited(bool dsl) d->connection->d_func()->readMoreLater(this); } +bool QHttpNetworkReply::supportsUserProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return (!d->isChunked() && !d->autoDecompress && d->bodyLength > 0); +} + +void QHttpNetworkReply::setUserProvidedDownloadBuffer(char* b) +{ + Q_D(QHttpNetworkReply); + if (supportsUserProvidedDownloadBuffer()) + d->userProvidedDownloadBuffer = b; +} + +char* QHttpNetworkReply::userProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return d->userProvidedDownloadBuffer; +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -207,7 +227,10 @@ bool QHttpNetworkReply::isPipeliningUsed() const QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), + : QHttpNetworkHeaderPrivate(newUrl) + , state(NothingDoneState) + , ssl(false) + , statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), chunkedTransferEncoding(false), connectionCloseEnabled(true), @@ -215,6 +238,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(), requestIsPrepared(false) ,pipeliningUsed(false), downstreamLimited(false) + ,userProvidedDownloadBuffer(0) { } @@ -448,6 +472,8 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) return -1; // unexpected EOF else if (haveRead == 0) break; // read more later + else if (haveRead == 1 && bytes == 0 && (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31)) + continue; // Ignore all whitespace that was trailing froma previous request on that socket bytes++; @@ -623,12 +649,32 @@ bool QHttpNetworkReplyPrivate::isConnectionCloseEnabled() // note this function can only be used for non-chunked, non-compressed with // known content length +qint64 QHttpNetworkReplyPrivate::readBodyVeryFast(QAbstractSocket *socket, char *b) +{ + // This first read is to flush the buffer inside the socket + qint64 haveRead = 0; + haveRead = socket->read(b, bodyLength - contentRead); + if (haveRead == -1) { + return 0; // ### error checking here; + } + contentRead += haveRead; + + if (contentRead == bodyLength) { + state = AllDoneState; + } + + return haveRead; +} + +// note this function can only be used for non-chunked, non-compressed with +// known content length qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb) { + qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); QByteArray bd; bd.resize(toBeRead); - qint64 haveRead = socket->read(bd.data(), bd.size()); + qint64 haveRead = socket->read(bd.data(), toBeRead); if (haveRead == -1) { bd.clear(); return 0; // ### error checking here; @@ -650,29 +696,34 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff { qint64 bytes = 0; if (isChunked()) { - bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) - } else if (bodyLength > 0) { // we have a Content-Length + // chunked transfer encoding (rfc 2616, sec 3.6) + bytes += readReplyBodyChunked(socket, out); + } else if (bodyLength > 0) { + // we have a Content-Length bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead); if (contentRead + bytes == bodyLength) state = AllDoneState; } else { + // no content length. just read what's possible bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } contentRead += bytes; return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QAbstractSocket *socket, QByteDataBuffer *out, qint64 size) { + // FIXME get rid of this function and just use readBodyFast and give it socket->bytesAvailable() qint64 bytes = 0; - Q_ASSERT(in); + Q_ASSERT(socket); Q_ASSERT(out); - int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); + while (toBeRead > 0) { QByteArray byteData; byteData.resize(toBeRead); - qint64 haveRead = in->read(byteData.data(), byteData.size()); + qint64 haveRead = socket->read(byteData.data(), byteData.size()); if (haveRead <= 0) { // ### error checking here byteData.clear(); @@ -684,25 +735,35 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer bytes += haveRead; size -= haveRead; - toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); } return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, QByteDataBuffer *out) { qint64 bytes = 0; - while (in->bytesAvailable()) { // while we can read from input - // if we are done with the current chunk, get the size of the new chunk + while (socket->bytesAvailable()) { if (currentChunkRead >= currentChunkSize) { + // For the first chunk and when we're done with a chunk currentChunkSize = 0; currentChunkRead = 0; if (bytes) { + // After a chunk char crlf[2]; - bytes += in->read(crlf, 2); // read the "\r\n" after the chunk + // read the "\r\n" after the chunk + qint64 haveRead = socket->read(crlf, 2); + // FIXME: This code is slightly broken and not optimal. What if the 2 bytes are not available yet?! + // For nice reasons (the toLong in getChunkSize accepting \n at the beginning + // it right now still works, but we should definitely fix this. + + if (haveRead != 2) + return bytes; // FIXME + bytes += haveRead; } - bytes += getChunkSize(in, ¤tChunkSize); + // Note that chunk size gets stored in currentChunkSize, what is returned is the bytes read + bytes += getChunkSize(socket, ¤tChunkSize); if (currentChunkSize == -1) break; } @@ -712,8 +773,8 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu break; } - // otherwise, try to read what is missing for this chunk - qint64 haveRead = readReplyBodyRaw (in, out, currentChunkSize - currentChunkRead); + // otherwise, try to begin reading this chunk / to read what is missing for this chunk + qint64 haveRead = readReplyBodyRaw (socket, out, currentChunkSize - currentChunkRead); currentChunkRead += haveRead; bytes += haveRead; @@ -723,22 +784,25 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu return bytes; } -qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) +qint64 QHttpNetworkReplyPrivate::getChunkSize(QAbstractSocket *socket, qint64 *chunkSize) { qint64 bytes = 0; char crlf[2]; *chunkSize = -1; - int bytesAvailable = in->bytesAvailable(); + + int bytesAvailable = socket->bytesAvailable(); + // FIXME rewrite to permanent loop without bytesAvailable while (bytesAvailable > bytes) { - qint64 sniffedBytes = in->peek(crlf, 2); + qint64 sniffedBytes = socket->peek(crlf, 2); int fragmentSize = fragment.size(); + // check the next two bytes for a "\r\n", skip blank lines if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n') ||(fragmentSize > 1 && fragment.endsWith('\r') && crlf[0] == '\n')) { - bytes += in->read(crlf, 1); // read the \r or \n + bytes += socket->read(crlf, 1); // read the \r or \n if (crlf[0] == '\r') - bytes += in->read(crlf, 1); // read the \n + bytes += socket->read(crlf, 1); // read the \n bool ok = false; // ignore the chunk-extension fragment = fragment.mid(0, fragment.indexOf(';')).trimmed(); @@ -748,10 +812,15 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) } else { // read the fragment to the buffer char c = 0; - bytes += in->read(&c, 1); + qint64 haveRead = socket->read(&c, 1); + if (haveRead < 0) { + return -1; // FIXME + } + bytes += haveRead; fragment.append(c); } } + return bytes; } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 4011c78..02ce248 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -128,6 +128,10 @@ public: QByteArray readAny(); void setDownstreamLimited(bool t); + bool supportsUserProvidedDownloadBuffer(); + void setUserProvidedDownloadBuffer(char*); + char* userProvidedDownloadBuffer(); + bool isFinished() const; bool isPipeliningUsed() const; @@ -147,6 +151,7 @@ Q_SIGNALS: void finished(); void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); void headerChanged(); + // FIXME we need to change this to qint64! void dataReadProgress(int done, int total); void dataSendProgress(qint64 done, qint64 total); @@ -168,15 +173,16 @@ public: qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QByteDataBuffer *out); + qint64 readBodyVeryFast(QAbstractSocket *socket, char *b); qint64 readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb); bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); void clearHttpLayerInformation(); - qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); - qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out); - qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); + qint64 readReplyBodyRaw(QAbstractSocket *in, QByteDataBuffer *out, qint64 size); + qint64 readReplyBodyChunked(QAbstractSocket *in, QByteDataBuffer *out); + qint64 getChunkSize(QAbstractSocket *in, qint64 *chunkSize); void appendUncompressedReplyData(QByteArray &qba); void appendUncompressedReplyData(QByteDataBuffer &data); @@ -205,6 +211,7 @@ public: } state; QHttpNetworkRequest request; + bool ssl; int statusCode; int majorVersion; int minorVersion; @@ -234,6 +241,8 @@ public: bool pipeliningUsed; bool downstreamLimited; + + char* userProvidedDownloadBuffer; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 639025e..d2f3212 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -63,6 +63,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest pipeliningAllowed = other.pipeliningAllowed; customVerb = other.customVerb; withCredentials = other.withCredentials; + ssl = other.ssl; } QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() @@ -73,6 +74,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) + && (ssl == other.ssl) && (uploadByteDevice == other.uploadByteDevice); } @@ -199,6 +201,15 @@ void QHttpNetworkRequest::setUrl(const QUrl &url) d->url = url; } +bool QHttpNetworkRequest::isSsl() const +{ + return d->ssl; +} +void QHttpNetworkRequest::setSsl(bool s) +{ + d->ssl = s; +} + qint64 QHttpNetworkRequest::contentLength() const { return d->contentLength(); diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 15cab73..123babc 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -116,6 +116,9 @@ public: bool withCredentials() const; void setWithCredentials(bool b); + bool isSsl() const; + void setSsl(bool); + void setUploadByteDevice(QNonContiguousByteDevice *bd); QNonContiguousByteDevice* uploadByteDevice() const; @@ -146,6 +149,7 @@ public: bool autoDecompress; bool pipeliningAllowed; bool withCredentials; + bool ssl; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 60f7dc6..c3d765b 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -146,7 +146,7 @@ QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() // and the special backends need to access this. void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) { - if (reply->isFinished()) + if (reply->isFinished) return; reply->emitUploadProgress(bytesSent, bytesTotal); } @@ -252,6 +252,17 @@ void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) reply->appendDownstreamData(data); } +// not actually appending data, it was already written to the user buffer +void QNetworkAccessBackend::writeDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + reply->appendDownstreamDataDownloadBuffer(bytesReceived, bytesTotal); +} + +char* QNetworkAccessBackend::getDownloadBuffer(qint64 size) +{ + return reply->getDownloadBuffer(size); +} + QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const { return reply->q_func()->header(header); diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 4fe6de6..9f8a01f 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -177,6 +177,10 @@ protected: qint64 nextDownstreamBlockSize() const; void writeDownstreamData(QByteDataBuffer &list); + // not actually appending data, it was already written to the user buffer + void writeDownstreamDataDownloadBuffer(qint64, qint64); + char* getDownloadBuffer(qint64); + public slots: // for task 251801, needs to be a slot to be called asynchronously void writeDownstreamData(QIODevice *data); diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index 4560153..710c258 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -65,10 +65,15 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("qrc") || !url.toLocalFile().isEmpty()) + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 || url.isLocalFile()) { return new QNetworkAccessFileBackend; - else if (!url.isEmpty() && url.authority().isEmpty()) { - // check if QFile could, in theory, open this URL + } else if (!url.scheme().isEmpty() && url.authority().isEmpty()) { + // check if QFile could, in theory, open this URL via the file engines + // it has to be in the format: + // prefix:path/to/file + // or prefix:/path/to/file + // + // this construct here must match the one below in open() QFileInfo fi(url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery)); if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists())) return new QNetworkAccessFileBackend; diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 1a59011..da336d0 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -77,7 +77,7 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("ftp")) + if (url.scheme().compare(QLatin1String("ftp"), Qt::CaseInsensitive) == 0) return new QNetworkAccessFtpBackend; return 0; } diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index f617244..8b9a99f 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -542,6 +542,9 @@ void QNetworkAccessHttpBackend::postRequest() break; // can't happen } + bool encrypt = (url().scheme().toLower() == QLatin1String("https")); + httpRequest.setSsl(encrypt); + httpRequest.setUrl(url()); QList<QByteArray> headers = request().rawHeaderList(); @@ -595,7 +598,6 @@ void QNetworkAccessHttpBackend::postRequest() httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList); #endif - connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); connect(httpReply, SIGNAL(finished()), SLOT(replyFinished())); connect(httpReply, SIGNAL(finishedWithError(QNetworkReply::NetworkError,QString)), SLOT(httpError(QNetworkReply::NetworkError,QString))); @@ -859,9 +861,33 @@ void QNetworkAccessHttpBackend::replyHeaderChanged() if (!isCachingEnabled()) setCachingEnabled(true); } + + // Check if a download buffer is supported from the HTTP reply + char *buf = 0; + if (httpReply->supportsUserProvidedDownloadBuffer()) { + // Check if a download buffer is supported by the user + buf = getDownloadBuffer(httpReply->contentLength()); + if (buf) { + httpReply->setUserProvidedDownloadBuffer(buf); + // If there is a download buffer we react on the progress signal + connect(httpReply, SIGNAL(dataReadProgress(int,int)), SLOT(replyDownloadProgressSlot(int,int))); + } + } + + // If there is no buffer, we react on the readyRead signal + if (!buf) { + connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); + } + metaDataChanged(); } +void QNetworkAccessHttpBackend::replyDownloadProgressSlot(int received, int total) +{ + // we can be sure here that there is a download buffer + writeDownstreamDataDownloadBuffer(received, total); +} + void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *auth) { @@ -1169,6 +1195,11 @@ bool QNetworkAccessHttpBackend::canResume() const return false; } + // If we're using a download buffer then we don't support resuming/migration + // right now. Too much trouble. + if (httpReply->userProvidedDownloadBuffer()) + return false; + return true; } diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index c4c88ae..fb12781 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -104,6 +104,7 @@ private slots: void replyReadyRead(); void replyFinished(); void replyHeaderChanged(); + void replyDownloadProgressSlot(int,int); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpCacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 837cf66..615793a 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -450,6 +450,8 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) : QObject(*new QNetworkAccessManagerPrivate, parent) { ensureInitialized(); + + qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); } /*! @@ -944,21 +946,20 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera { Q_D(QNetworkAccessManager); + bool isLocalFile = req.url().isLocalFile(); + // fast path for GET on file:// URLs - // Also if the scheme is empty we consider it a file. // The QNetworkAccessFileBackend will right now only be used // for PUT or qrc:// if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && (req.url().scheme() == QLatin1String("file") - || req.url().scheme().isEmpty())) { + && isLocalFile) { return new QFileNetworkReply(this, req, op); } #ifndef QT_NO_BEARERMANAGEMENT // Return a disabled network reply if network access is disabled. // Except if the scheme is empty or file://. - if (!d->networkAccessible && !(req.url().scheme() == QLatin1String("file") || - req.url().scheme().isEmpty())) { + if (!d->networkAccessible && !isLocalFile) { return new QDisabledNetworkReply(this, req, op); } @@ -992,7 +993,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera if (d->cookieJar) { QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url()); if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); } } @@ -1000,7 +1001,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QUrl url = request.url(); QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT - if (req.url().scheme() != QLatin1String("file") && !req.url().scheme().isEmpty()) { + if (!isLocalFile) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index c8b8c1f..b40ee3c 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -49,6 +49,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() : readBufferMaxSize(0), operation(QNetworkAccessManager::UnknownOperation), errorCode(QNetworkReply::NoError) + , isFinished(false) { // set the default attribute values attributes.insert(QNetworkRequest::ConnectionEncryptedAttribute, false); @@ -468,7 +469,7 @@ QNetworkReply::NetworkError QNetworkReply::error() const */ bool QNetworkReply::isFinished() const { - return d_func()->isFinished(); + return d_func()->isFinished; } /*! @@ -724,6 +725,21 @@ void QNetworkReply::setError(NetworkError errorCode, const QString &errorString) } /*! + \since 4.8 + Sets the reply as \a finished. + + After having this set the replies data must not change. + + \sa isFinished() +*/ +void QNetworkReply::setFinished(bool finished) +{ + Q_D(QNetworkReply); + d->isFinished = finished; +} + + +/*! Sets the URL being processed to be \a url. Normally, the URL matches that of the request that was posted, but for a variety of reasons it can be different (for example, a file path being made diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index acb7379..b39fd32 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -163,6 +163,7 @@ protected: void setOperation(QNetworkAccessManager::Operation operation); void setRequest(const QNetworkRequest &request); void setError(NetworkError errorCode, const QString &errorString); + void setFinished(bool); void setUrl(const QUrl &url); void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value); void setRawHeader(const QByteArray &headerName, const QByteArray &value); diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h index d7b8ab0..2e2e0bc 100644 --- a/src/network/access/qnetworkreply_p.h +++ b/src/network/access/qnetworkreply_p.h @@ -71,12 +71,11 @@ public: qint64 readBufferMaxSize; QNetworkAccessManager::Operation operation; QNetworkReply::NetworkError errorCode; + bool isFinished; static inline void setManager(QNetworkReply *reply, QNetworkAccessManager *manager) { reply->d_func()->manager = manager; } - virtual bool isFinished() const { return false; } - Q_DECLARE_PUBLIC(QNetworkReply) }; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 31ee2a4..70418e9 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -49,10 +49,16 @@ #include "QtNetwork/qnetworksession.h" #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessmanager_p.h" +#include <QVarLengthArray> #include <QtCore/QCoreApplication> QT_BEGIN_NAMESPACE +typedef QSharedPointer<QVarLengthArray<char, 0> > QVarLengthArraySharedPointer; +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QVarLengthArraySharedPointer) + +QT_BEGIN_NAMESPACE inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() : backend(0), outgoingData(0), outgoingDataBuffer(0), @@ -62,6 +68,8 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), preMigrationDownloaded(-1), httpStatusCode(0), state(Idle) + , downloadBuffer(0) + , downloadBufferPosition(0) { } @@ -125,6 +133,10 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (!copyDevice || !q->isOpen()) return; + // FIXME Optimize to use download buffer if it is a QBuffer. + // Needs to be done where sendCacheContents() (?) of HTTP is emitting + // metaDataChanged ? + forever { qint64 bytesToRead = nextDownstreamBlockSize(); if (bytesToRead == 0) @@ -543,8 +555,6 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() { Q_Q(QNetworkReplyImpl); - QPointer<QNetworkReplyImpl> qq = q; - QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; @@ -555,13 +565,10 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); - // hopefully we haven't been deleted here - if (!qq.isNull()) { - resumeNotificationHandling(); - // do we still have room in the buffer? - if (nextDownstreamBlockSize() > 0) - backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); - } + resumeNotificationHandling(); + // do we still have room in the buffer? + if (nextDownstreamBlockSize() > 0) + backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); } // this is used when it was fetched from the cache, right? @@ -595,6 +602,55 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) qFatal("QNetworkReplyImplPrivate::appendDownstreamData not implemented"); } +char* QNetworkReplyImplPrivate::getDownloadBuffer(qint64 size) +{ + Q_Q(QNetworkReplyImpl); + + // Check attribute() if allocating a buffer of that size can be allowed + if (!downloadBuffer) { + QVariant bufferAllocationPolicy = request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute); + if (bufferAllocationPolicy.isValid() && bufferAllocationPolicy.toLongLong() >= size) { + downloadBufferArray = QSharedPointer<QVarLengthArray<char, 0> >(new QVarLengthArray<char, 0>()); + downloadBufferArray->reserve(size); + + downloadBuffer = downloadBufferArray->data(); + + q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue<QSharedPointer<QVarLengthArray<char, 0> > > (downloadBufferArray)); + } + } + + return downloadBuffer; +} + +void QNetworkReplyImplPrivate::appendDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + Q_Q(QNetworkReplyImpl); + if (!q->isOpen()) + return; + + if (cacheEnabled && !cacheSaveDevice) + initCacheSaveDevice(); + + if (cacheSaveDevice && bytesReceived == bytesTotal) { +// if (lastBytesDownloaded == -1) +// lastBytesDownloaded = 0; +// cacheSaveDevice->write(downloadBuffer + lastBytesDownloaded, bytesReceived - lastBytesDownloaded); + + // Write everything in one go if we use a download buffer. might be more performant. + cacheSaveDevice->write(downloadBuffer, bytesTotal); + } + + bytesDownloaded = bytesReceived; + lastBytesDownloaded = bytesReceived; + + // Update the array so our user (e.g. QtWebKit) knows the real size + if (bytesReceived > 0) + downloadBufferArray->resize(bytesReceived); + + emit q->downloadProgress(bytesDownloaded, bytesTotal); + emit q->readyRead(); +} + void QNetworkReplyImplPrivate::finished() { Q_Q(QNetworkReplyImpl); @@ -633,6 +689,8 @@ void QNetworkReplyImplPrivate::finished() resumeNotificationHandling(); state = Finished; + q->setFinished(true); + pendingNotifications.clear(); pauseNotificationHandling(); @@ -703,11 +761,6 @@ void QNetworkReplyImplPrivate::sslErrors(const QList<QSslError> &errors) #endif } -bool QNetworkReplyImplPrivate::isFinished() const -{ - return (state == Finished || state == Aborted); -} - QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent) : QNetworkReply(*new QNetworkReplyImplPrivate, parent) { @@ -742,7 +795,7 @@ void QNetworkReplyImpl::abort() QNetworkReply::close(); if (d->state != QNetworkReplyImplPrivate::Finished) { - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -770,7 +823,7 @@ void QNetworkReplyImpl::close() QNetworkReply::close(); - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -789,6 +842,13 @@ bool QNetworkReplyImpl::canReadLine () const */ qint64 QNetworkReplyImpl::bytesAvailable() const { + // Special case for the "zero copy" download buffer + Q_D(const QNetworkReplyImpl); + if (d->downloadBuffer) { + qint64 maxAvail = d->downloadBufferArray->size() - d->downloadBufferPosition; + return QNetworkReply::bytesAvailable() + maxAvail; + } + return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount(); } @@ -843,8 +903,22 @@ void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &er qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) { Q_D(QNetworkReplyImpl); + + // Special case code if we have the "zero copy" download buffer + if (d->downloadBuffer) { + qint64 maxAvail = qMin<qint64>(d->downloadBufferArray->size() - d->downloadBufferPosition, maxlen); + if (maxAvail == 0) + return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? + qMemCopy(data, d->downloadBuffer + d->downloadBufferPosition, maxAvail); + d->downloadBufferPosition += maxAvail; + return maxAvail; + } + + if (d->readBuffer.isEmpty()) return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); if (maxlen == 1) { diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 38084bd..2cb3082 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -62,6 +62,7 @@ #include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" #include "private/qbytedata_p.h" +#include <QVarLengthArray> QT_BEGIN_NAMESPACE @@ -163,14 +164,15 @@ public: void appendDownstreamData(QIODevice *data); void appendDownstreamData(const QByteArray &data); + char* getDownloadBuffer(qint64 size); + void appendDownstreamDataDownloadBuffer(qint64, qint64); + void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); void redirectionRequested(const QUrl &target); void sslErrors(const QList<QSslError> &errors); - bool isFinished() const; - QNetworkAccessBackend *backend; QIODevice *outgoingData; QRingBuffer *outgoingDataBuffer; @@ -191,6 +193,7 @@ public: QList<QNetworkProxy> proxyList; #endif + // Used for normal downloading. For "zero copy" the downloadBuffer is used QByteDataBuffer readBuffer; qint64 bytesDownloaded; qint64 lastBytesDownloaded; @@ -202,6 +205,11 @@ public: State state; + // only used when the "zero copy" style is used. Else readBuffer is used. + QSharedPointer< QVarLengthArray<char, 0> > downloadBufferArray; + char* downloadBuffer; + qint64 downloadBufferPosition; + Q_DECLARE_PUBLIC(QNetworkReplyImpl) }; diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index d3084cf..09ec4c2 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -766,7 +766,7 @@ static QVariant parseCookieHeader(const QByteArray &raw) result += parsed; } - return qVariantFromValue(result); + return QVariant::fromValue(result); } static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value) @@ -799,7 +799,7 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy return parseCookieHeader(value); case QNetworkRequest::SetCookieHeader: - return qVariantFromValue(QNetworkCookie::parseCookies(value)); + return QVariant::fromValue(QNetworkCookie::parseCookies(value)); default: Q_ASSERT(0); diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 348b0d2..7908182 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -56,9 +56,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) -#endif //#define QHOSTINFO_DEBUG @@ -87,10 +85,8 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 0 - The slot is invoked when the results are ready. (If you use - Qt for Embedded Linux and disabled multithreading support by defining - \c QT_NO_THREAD, lookupHost() will block until the lookup has - finished.) The results are stored in a QHostInfo object. Call + The slot is invoked when the results are ready. The results are + stored in a QHostInfo object. Call addresses() to get the list of IP addresses for the host, and hostName() to get the host name that was looked up. @@ -176,14 +172,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, return id; } -#ifdef QT_NO_THREAD - QHostInfo hostInfo = QHostInfoAgent::fromName(name); - hostInfo.setLookupId(id); - QScopedPointer<QHostInfoResult> result(new QHostInfoResult); - QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)), - receiver, member, Qt::QueuedConnection); - result.data()->emitResultsReady(hostInfo); -#else QHostInfoLookupManager *manager = theHostInfoLookupManager(); if (manager) { // the application is still alive @@ -204,8 +192,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); } -#endif - return id; } @@ -216,12 +202,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, */ void QHostInfo::abortHostLookup(int id) { -#ifndef QT_NO_THREAD theHostInfoLookupManager()->abortLookup(id); -#else - // we cannot abort if it was non threaded.. the result signal has already been posted - Q_UNUSED(id); -#endif } /*! @@ -422,7 +403,6 @@ void QHostInfo::setErrorString(const QString &str) \sa hostName() */ -#ifndef QT_NO_THREAD QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i) { setAutoDelete(true); @@ -747,6 +727,4 @@ void QHostInfoCache::clear() cache.clear(); } -#endif // QT_NO_THREAD - QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 85d14c2..134335f 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -60,8 +60,6 @@ #include "QtCore/qwaitcondition.h" #include "QtCore/qobject.h" #include "QtCore/qpointer.h" - -#ifndef QT_NO_THREAD #include "QtCore/qthread.h" #include "QtCore/qthreadpool.h" #include "QtCore/qmutex.h" @@ -70,7 +68,7 @@ #include "QtCore/qqueue.h" #include <QTime> #include <QCache> -#endif + QT_BEGIN_NAMESPACE @@ -112,7 +110,6 @@ public: int lookupId; }; -#ifndef QT_NO_THREAD // These functions are outside of the QHostInfo class and strictly internal. // Do NOT use them outside of QAbstractSocket. QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id); @@ -192,8 +189,6 @@ private slots: void waitForThreadPoolDone() { threadPool.waitForDone(); } }; -#endif - QT_END_NAMESPACE #endif // QHOSTINFO_P_H diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 3112dd6..b641711 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -132,9 +132,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index b30204b..1671ae4 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -39,11 +39,6 @@ ** ****************************************************************************/ -#if defined Q_CC_MSVC && _MSC_VER <=1300 -//VC.net 2002 support for templates doesn't match some PSDK requirements -#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) -#endif - #include <winsock2.h> #include "qhostinfo_p.h" @@ -115,9 +110,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 505db71..3218662 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -466,9 +466,6 @@ QAbstractSocketPrivate::QAbstractSocketPrivate() peerPort(0), socketEngine(0), cachedSocketDescriptor(-1), -#ifdef Q_OS_LINUX - addToBytesAvailable(0), -#endif readBufferMaxSize(0), readBuffer(QABSTRACTSOCKET_BUFFERSIZE), writeBuffer(QABSTRACTSOCKET_BUFFERSIZE), @@ -630,8 +627,9 @@ bool QAbstractSocketPrivate::canReadNotification() // only emit readyRead() when not recursing, and only if there is data available bool hasData = newBytes > 0 #ifndef QT_NO_UDPSOCKET - || (!isBuffered && socketEngine && socketEngine->hasPendingDatagrams()) + || (!isBuffered && socketType != QAbstractSocket::TcpSocket && socketEngine && socketEngine->hasPendingDatagrams()) #endif + || (!isBuffered && socketType == QAbstractSocket::TcpSocket && socketEngine) ; if (!emittedReadyRead && hasData) { @@ -1132,10 +1130,6 @@ bool QAbstractSocketPrivate::readFromSocket() Q_Q(QAbstractSocket); // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable(); -#ifdef Q_OS_LINUX - if (bytesToRead > 0) // ### See setSocketDescriptor() - bytesToRead += addToBytesAvailable; -#endif if (bytesToRead == 0) { // Under heavy load, certain conditions can trigger read notifications // for socket notifiers on which there is no activity. If we continue @@ -1340,10 +1334,6 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint d->localAddress.clear(); d->peerAddress.clear(); d->peerName = hostName; -#ifdef Q_OS_LINUX - // ### See setSocketDescriptor(). - d->addToBytesAvailable = 0; -#endif if (d->hostLookupId != -1) { QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; @@ -1361,8 +1351,11 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint } #endif - if (!d_func()->isBuffered) - openMode |= QAbstractSocket::Unbuffered; + if (openMode & QIODevice::Unbuffered) + d->isBuffered = false; // Unbuffered QTcpSocket + else if (!d_func()->isBuffered) + openMode |= QAbstractSocket::Unbuffered; // QUdpSocket + QIODevice::open(openMode); d->state = HostLookupState; emit stateChanged(d->state); @@ -1442,10 +1435,12 @@ qint64 QAbstractSocket::bytesAvailable() const { Q_D(const QAbstractSocket); qint64 available = QIODevice::bytesAvailable(); - if (d->isBuffered) - available += (qint64) d->readBuffer.size(); - else if (d->socketEngine && d->socketEngine->isValid()) + + available += (qint64) d->readBuffer.size(); + + if (!d->isBuffered && d->socketEngine && d->socketEngine->isValid()) available += d->socketEngine->bytesAvailable(); + #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::bytesAvailable() == %llu", available); #endif @@ -1603,17 +1598,6 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock d->peerAddress = d->socketEngine->peerAddress(); d->cachedSocketDescriptor = socketDescriptor; -#ifdef Q_OS_LINUX - // ### This is a workaround for certain broken Linux kernels, when using - // QTcpSocket with a Unix domain socket. It was introduced around 2.6.9, - // and fixed at some point after that. - // http://archive.linux-usenet.com/index-t-73300.html - // We can provide a better workaround for this: readFromSocket() can loop - // while reading, but this must happen without triggering an implicit - // close because of reading after the socket has closed. - d->addToBytesAvailable = 4096; -#endif - return true; } @@ -2089,42 +2073,50 @@ bool QAbstractSocket::flush() qint64 QAbstractSocket::readData(char *data, qint64 maxSize) { Q_D(QAbstractSocket); - if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) - d->socketEngine->setReadNotificationEnabled(true); - if (!d->isBuffered) { - if (!d->socketEngine) - return -1; // no socket engine is probably EOF - qint64 readBytes = d->socketEngine->read(data, maxSize); - if (readBytes < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - } - if (!d->socketEngine->isReadNotificationEnabled()) - d->socketEngine->setReadNotificationEnabled(true); -#if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", - data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, - readBytes); -#endif - return readBytes; - } - - if (d->readBuffer.isEmpty()) + // This is for a buffered QTcpSocket + if (d->isBuffered && d->readBuffer.isEmpty()) // if we're still connected, return 0 indicating there may be more data in the future // if we're not connected, return -1 indicating EOF return d->state == QAbstractSocket::ConnectedState ? qint64(0) : qint64(-1); - // If readFromSocket() read data, copy it to its destination. - if (maxSize == 1) { + // short cut for a char read if we have something in the buffer + if (maxSize == 1 && !d->readBuffer.isEmpty()) { *data = d->readBuffer.getChar(); #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1", + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1 [char buffer]", data, isprint(int(uchar(*data))) ? *data : '?', *data); #endif + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); return 1; } + // Special case for an Unbuffered QTcpSocket + // Re-filling the buffer. + if (d->socketType == TcpSocket + && !d->isBuffered + && d->readBuffer.size() < maxSize + && d->readBufferMaxSize > 0 + && maxSize < d->readBufferMaxSize + && d->socketEngine) { + // Our buffer is empty and a read() was requested for a byte amount that is smaller + // than the readBufferMaxSize. This means that we should fill our buffer since we want + // such small reads come from the buffer and not always go to the costly socket engine read() + qint64 bytesToRead = d->socketEngine->bytesAvailable(); + if (bytesToRead > 0) { + char *ptr = d->readBuffer.reserve(bytesToRead); + qint64 readBytes = d->socketEngine->read(ptr, bytesToRead); + if (readBytes == -2) { + // No bytes currently available for reading. + d->readBuffer.chop(bytesToRead); + } else { + d->readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes))); + } + } + } + + // First try to satisfy the read from the buffer qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { @@ -2136,8 +2128,50 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) d->readBuffer.free(bytesToReadFromThisBlock); } + if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) + d->socketEngine->setReadNotificationEnabled(true); + + if (readSoFar > 0) { + // we read some data from buffer. + // Just return, readyRead will be emitted again +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', %lli) == %lli [buffer]", + data, isprint(int(uchar(*data))) ? *data : '?', *data, maxSize, readSoFar); +#endif + + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); + return readSoFar; + } + + // This code path is for Unbuffered QTcpSocket or for connected UDP + + if (!d->isBuffered) { + if (!d->socketEngine) + return -1; // no socket engine is probably EOF + qint64 readBytes = d->socketEngine->read(data, maxSize); + if (readBytes == -2) { + // -2 from the engine means no bytes available (EAGAIN) so read more later + return 0; + } else if (readBytes < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + } else if (!d->socketEngine->isReadNotificationEnabled()) { + // Only do this when there was no error + d->socketEngine->setReadNotificationEnabled(true); + } + +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [engine]", + data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, + readBytes); +#endif + return readBytes; + } + + #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [unreachable]", data, qt_prettyDebug(data, qMin<qint64>(32, readSoFar), readSoFar).data(), maxSize, readSoFar); #endif @@ -2162,7 +2196,23 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return -1; } - if (!d->isBuffered) { + if (!d->isBuffered && d->socketType == TcpSocket && d->writeBuffer.isEmpty()) { + // This code is for the new Unbuffered QTcpSocket use case + qint64 written = d->socketEngine->write(data, size); + if (written < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + return written; + } else if (written < size) { + // Buffer what was not written yet + char *ptr = d->writeBuffer.reserve(size - written); + memcpy(ptr, data + written, size - written); + if (d->socketEngine) + d->socketEngine->setWriteNotificationEnabled(true); + } + return size; // size=actually written + what has been buffered + } else if (!d->isBuffered && d->socketType != TcpSocket) { + // This is for a QUdpSocket that was connect()ed qint64 written = d->socketEngine->write(data, size); if (written < 0) { d->socketError = d->socketEngine->error(); @@ -2181,6 +2231,12 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return written; } + // This is the code path for normal buffered QTcpSocket or + // unbuffered QTcpSocket when there was already something in the + // write buffer and therefore we could not do a direct engine write. + // We just write to our write buffer and enable the write notifier + // The write notifier then flush()es the buffer. + char *ptr = d->writeBuffer.reserve(size); if (size == 1) *ptr = *data; diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index b51c301..6c333d3 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -138,9 +138,6 @@ public: void setupSocketNotifiers(); bool readFromSocket(); -#ifdef Q_OS_LINUX - qint64 addToBytesAvailable; -#endif qint64 readBufferMaxSize; QRingBuffer readBuffer; QRingBuffer writeBuffer; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index fe28863..1086386 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -887,7 +887,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { - qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket"); + qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); return -1; } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 40b3641..4b5f53e 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -46,24 +46,29 @@ #include <QMetaEnum> #endif +// #define QT_GL_SHARED_SHADER_DEBUG QT_BEGIN_NAMESPACE -static void qt_shared_shaders_free(void *data) +class QGLShaderStorage { - delete reinterpret_cast<QGLEngineSharedShaders *>(data); -} +public: + QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { + QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData(); + if (!shaders) + shaders = new QGLContextGroupResource<QGLEngineSharedShaders>(); + return shaders->value(context); + } + +private: + QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage; +}; -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_shaders, (qt_shared_shaders_free)) +Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage); QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context) { - QGLEngineSharedShaders *p = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context)); - } - return p; + return qt_shader_storage()->shadersForThread(context); } const char* QGLEngineSharedShaders::qShaderSnippets[] = { @@ -170,18 +175,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); if (!vertexShader->compileSourceCode(source)) qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); - fragShader = new QGLShader(QGLShader::Fragment, context, this); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); - simpleShaderProg = new QGLShaderProgram(context, this); + simpleShaderProg = new QGLShaderProgram(context, 0); simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); @@ -198,18 +205,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); if (!vertexShader->compileSourceCode(source)) qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ImageSrcFragmentShader]); - fragShader = new QGLShader(QGLShader::Fragment, context, this); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); - blitShaderProg = new QGLShaderProgram(context, this); + blitShaderProg = new QGLShaderProgram(context, 0); blitShaderProg->addShader(vertexShader); blitShaderProg->addShader(fragShader); blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); @@ -220,13 +229,21 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) << simpleShaderProg->log(); } +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif } QGLEngineSharedShaders::~QGLEngineSharedShaders() { - QList<QGLEngineShaderProg*>::iterator itr; - for (itr = cachedPrograms.begin(); itr != cachedPrograms.end(); ++itr) - delete *itr; +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> ~QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif + qDeleteAll(shaders); + shaders.clear(); + + qDeleteAll(cachedPrograms); + cachedPrograms.clear(); if (blitShaderProg) { delete blitShaderProg; @@ -276,7 +293,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) source.append(qShaderSnippets[prog.maskFragShader]); - fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); + fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0); + shaders.append(fragShader); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging @@ -302,7 +320,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.clear(); source.append(qShaderSnippets[prog.mainVertexShader]); source.append(qShaderSnippets[prog.positionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); + vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0); + shaders.append(vertexShader); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); @@ -320,7 +339,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg = new QGLEngineShaderProg(prog); // If the shader program's not found in the cache, create it now. - newProg->program = new QGLShaderProgram(ctxGuard.context(), this); + newProg->program = new QGLShaderProgram(ctxGuard.context(), 0); newProg->program->addShader(vertexShader); newProg->program->addShader(fragShader); @@ -413,7 +432,6 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) currentShaderProg(0) { sharedShaders = QGLEngineSharedShaders::shadersForContext(context); - connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot())); } QGLEngineShaderManager::~QGLEngineShaderManager() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 06b96ae..e5ababf 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -259,9 +259,9 @@ static const GLuint QT_PMV_MATRIX_3_ATTR = 5; class QGLEngineShaderProg; -class QGLEngineSharedShaders : public QObject +class QGLEngineSharedShaders { - Q_OBJECT + Q_GADGET public: enum SnippetName { @@ -364,14 +364,12 @@ public: // full. void cleanupCustomStage(QGLCustomShaderStage* stage); -signals: - void shaderProgNeedsChanging(); - private: QGLSharedResourceGuard ctxGuard; QGLShaderProgram *blitShaderProg; QGLShaderProgram *simpleShaderProg; QList<QGLEngineShaderProg*> cachedPrograms; + QList<QGLShader *> shaders; static const char* qShaderSnippets[TotalSnippetCount]; }; @@ -492,9 +490,6 @@ public: QGLEngineSharedShaders* sharedShaders; -private slots: - void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; } - private: QGLContext* ctx; bool shaderProgNeedsChanging; diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index a1495dd..cbd5eb8 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -42,29 +42,33 @@ #include "qglgradientcache_p.h" #include <private/qdrawhelper_p.h> #include <private/qgl_p.h> - +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -static void QGL2GradientCache_free(void *ptr) +class QGL2GradientCacheWrapper { - delete reinterpret_cast<QGL2GradientCache *>(ptr); -} +public: + QGL2GradientCache *cacheForContext(const QGLContext *context) { + QMutexLocker lock(&m_mutex); + return m_resource.value(context); + } -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) +private: + QGLContextGroupResource<QGL2GradientCache> m_resource; + QMutex m_mutex; +}; + +Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches) QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) { - QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - p = new QGL2GradientCache; - qt_gradient_caches()->insert(context, p); - } - return p; + return qt_gradient_caches()->cacheForContext(context); } -void QGL2GradientCache::cleanCache() { +void QGL2GradientCache::cleanCache() +{ + QMutexLocker lock(&m_mutex); QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { const CacheInfo &cache_info = it.value(); @@ -75,6 +79,7 @@ void QGL2GradientCache::cleanCache() { GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { + QMutexLocker lock(&m_mutex); quint64 hash_val = 0; QGradientStops stops = gradient.stops(); @@ -88,7 +93,9 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) else { do { const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) { + if (cache_info.stops == stops && cache_info.opacity == opacity + && cache_info.interpolationMode == gradient.interpolationMode()) + { return cache_info.texId; } ++it; diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 0a5f846..7e93d87 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -54,6 +54,7 @@ #include <QObject> #include <QtOpenGL/QtOpenGL> #include <private/qgl_p.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -75,22 +76,22 @@ class QGL2GradientCache public: static QGL2GradientCache *cacheForContext(const QGLContext *context); - QGL2GradientCache() { } - ~QGL2GradientCache() {cleanCache();} + QGL2GradientCache(const QGLContext *) {} + ~QGL2GradientCache() { cleanCache(); } GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } -protected: +private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); - void cleanCache(); QGLGradientColorTableHash cache; + QMutex m_mutex; }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 18192e3..6e56553 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1461,16 +1461,18 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QOpenGL2PaintEngineState *s = q->state(); + void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context()); QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform()); + (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(cacheKey, glyphType, QTransform()); if (!cache || cache->cacheType() != glyphType) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); - staticTextItem->fontEngine->setGlyphCache(ctx, cache); + staticTextItem->fontEngine->setGlyphCache(cacheKey, cache); } cache->setPaintEnginePrivate(this); cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, staticTextItem->glyphPositions); + cache->fillInPendingGlyphs(); if (cache->width() == 0 || cache->height() == 0) return; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 410cf21..53a2f3a 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -52,43 +52,41 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif -QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) +QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) - , ctx(context) - , m_width(0) - , m_height(0) + , ctx(0) + , pex(0) { - // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where - // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The - // workaround is to use a system-memory copy of the glyph cache for this device. - // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and - // be slower, so that is not desireable. - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glGenFramebuffers(1, &m_fbo); - - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(contextDestroyed(const QGLContext*))); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); +#endif + setContext(context); } QGLTextureGlyphCache::~QGLTextureGlyphCache() { - if (ctx) { - QGLShareContextScope scope(ctx); - - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glDeleteFramebuffers(1, &m_fbo); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> ~QGLTextureGlyphCache() %p.", this); +#endif +} - if (m_width || m_height) - glDeleteTextures(1, &m_texture); - } +void QGLTextureGlyphCache::setContext(const QGLContext *context) +{ + ctx = context; + m_h = 0; } void QGLTextureGlyphCache::createTextureData(int width, int height) { + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::createTextureData: Called with no context"); + return; + } + // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. - if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) + if ((pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); // Make the lower glyph texture size 16 x 16. @@ -97,11 +95,12 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (height < 16) height = 16; - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + glGenTextures(1, &glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); - m_width = width; - m_height = height; + glyphTexture->m_width = width; + glyphTexture->m_height = height; QVarLengthArray<uchar> data(width * height); for (int i = 0; i < data.size(); ++i) @@ -118,8 +117,14 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) void QGLTextureGlyphCache::resizeTextureData(int width, int height) { - int oldWidth = m_width; - int oldHeight = m_height; + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); + return; + } + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + + int oldWidth = glyphTexture->m_width; + int oldHeight = glyphTexture->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) @@ -127,10 +132,10 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (height < 16) height = 16; - GLuint oldTexture = m_texture; + GLuint oldTexture = glyphTexture->m_texture; createTextureData(width, height); - - if (ctx->d_ptr->workaround_brokenFBOReadBack) { + + if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); @@ -141,7 +146,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); @@ -196,7 +201,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); @@ -213,10 +218,16 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) { - if (ctx->d_ptr->workaround_brokenFBOReadBack) { + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::fillTexture: Called with no context"); + return; + } + + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; @@ -224,7 +235,6 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); bits += texture.bytesPerLine(); } - return; } @@ -254,7 +264,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) } } - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 6bcd655..2ae3a64 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -57,16 +57,51 @@ #include <private/qgl_p.h> #include <qglshaderprogram.h> +// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG QT_BEGIN_NAMESPACE class QGL2PaintEngineExPrivate; -class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache +struct QGLGlyphTexture +{ + QGLGlyphTexture(const QGLContext *ctx) + : m_width(0) + , m_height(0) + { + if (ctx && !ctx->d_ptr->workaround_brokenFBOReadBack) + glGenFramebuffers(1, &m_fbo); + +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + } + + ~QGLGlyphTexture() { + const QGLContext *ctx = QGLContext::currentContext(); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + // At this point, the context group is made current, so it's safe to + // release resources without a makeCurrent() call + if (ctx) { + if (!ctx->d_ptr->workaround_brokenFBOReadBack) + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + } + } + + GLuint m_texture; + GLuint m_fbo; + int m_width; + int m_height; +}; + +class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache { - Q_OBJECT public: - QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); + QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); virtual void createTextureData(int width, int height); @@ -74,47 +109,33 @@ public: virtual void fillTexture(const Coord &c, glyph_t glyph); virtual int glyphPadding() const; - inline GLuint texture() const { return m_texture; } + inline GLuint texture() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_texture : 0; + } - inline int width() const { return m_width; } - inline int height() const { return m_height; } + inline int width() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_width : 0; + } + inline int height() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_height : 0; + } inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } - -public Q_SLOTS: - void contextDestroyed(const QGLContext *context) { - if (context == ctx) { - const QGLContext *nextCtx = qt_gl_transfer_context(ctx); - if (!nextCtx) { - // the context may not be current, so we cannot directly - // destroy the fbo and texture here, but since the context - // is about to be destroyed, the GL server will do the - // clean up for us anyway - m_fbo = 0; - m_texture = 0; - ctx = 0; - } else { - // since the context holding the texture is shared, and - // about to be destroyed, we have to transfer ownership - // of the texture to one of the share contexts - ctx = const_cast<QGLContext *>(nextCtx); - } - } - } + void setContext(const QGLContext *context); + inline const QGLContext *context() const { return ctx; } private: - QGLContext *ctx; + QGLContextGroupResource<QGLGlyphTexture> m_textureResource; + const QGLContext *ctx; QGL2PaintEngineExPrivate *pex; - - GLuint m_texture; - GLuint m_fbo; - - int m_width; - int m_height; - - QGLShaderProgram *m_program; }; QT_END_NAMESPACE diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 0e82467..c7ca4bc 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -20,6 +20,7 @@ contains(QT_CONFIG, egl):CONFIG += egl HEADERS += qgl.h \ qgl_p.h \ qglcolormap.h \ + qglfunctions.h \ qglpixelbuffer.h \ qglpixelbuffer_p.h \ qglframebufferobject.h \ @@ -29,8 +30,9 @@ HEADERS += qgl.h \ qglbuffer.h \ -SOURCES += qgl.cpp \ +SOURCES += qgl.cpp \ qglcolormap.cpp \ + qglfunctions.cpp \ qglpixelbuffer.cpp \ qglframebufferobject.cpp \ qglextensions.cpp \ diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 9e69816..aac6db4 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -94,6 +94,8 @@ #include <qmutex.h> +// #define QT_GL_CONTEXT_RESOURCE_DEBUG + QT_BEGIN_NAMESPACE #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) @@ -1657,6 +1659,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) #if defined(Q_WS_WIN) dc = 0; win = 0; + threadId = 0; pixelFormatId = 0; cmap = 0; hbitmap = 0; @@ -2062,6 +2065,9 @@ QGLContext::~QGLContext() // remove any textures cached in this context QGLTextureCache::instance()->removeContextTextures(this); + // clean up resources specific to this context + d_ptr->cleanup(); + // clean up resources belonging to this context's group d_ptr->group->cleanupResources(this); QGLSignalProxy::instance()->emitAboutToDestroyContext(this); @@ -2070,6 +2076,10 @@ QGLContext::~QGLContext() void QGLContextPrivate::cleanup() { + QHash<QGLContextResourceBase *, void *>::ConstIterator it; + for (it = m_resources.begin(); it != m_resources.end(); ++it) + it.key()->freeResource(it.value()); + m_resources.clear(); } #define ctx q_ptr @@ -2132,20 +2142,10 @@ void QGLContextPrivate::swapRegion(const QRegion *) GLuint QGLContext::bindTexture(const QString &fileName) { - Q_D(QGLContext); - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QGLDDSCache::const_iterator it = dds_cache->constFind(fileName); - if (it != dds_cache->constEnd()) { - glBindTexture(GL_TEXTURE_2D, it.value()); - return it.value(); - } - QGLTexture texture(this); QSize size = texture.bindCompressedTexture(fileName); if (!size.isValid()) return 0; - - dds_cache->insert(fileName, texture.id); return texture.id; } @@ -2585,7 +2585,8 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, const QX11Info *xinfo = qt_x11Info(paintDevice); if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType && xinfo && xinfo->screen() == pixmap.x11Info().screen() - && target == GL_TEXTURE_2D) + && target == GL_TEXTURE_2D + && QApplication::instance()->thread() == QThread::currentThread()) { if (!workaround_brokenTextureFromPixmap_init) { workaround_brokenTextureFromPixmap_init = true; @@ -2806,24 +2807,8 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, Q */ void QGLContext::deleteTexture(GLuint id) { - Q_D(QGLContext); - if (QGLTextureCache::instance()->remove(this, id)) return; - - // check the DDS cache if the texture wasn't found in the pixmap/image - // cache - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QList<QString> ddsKeys = dds_cache->keys(); - for (int i = 0; i < ddsKeys.size(); ++i) { - GLuint texture = dds_cache->value(ddsKeys.at(i)); - if (id == texture) { - dds_cache->remove(ddsKeys.at(i)); - break; - } - } - - // Finally, actually delete the texture ID glDeleteTextures(1, &id); } @@ -4141,13 +4126,7 @@ bool QGLWidget::event(QEvent *e) } #if defined(Q_WS_X11) - // prevents X errors on some systems, where we get a flush to a - // hidden widget - if (e->type() == QEvent::Hide) { - makeCurrent(); - glFinish(); - doneCurrent(); - } else if (e->type() == QEvent::ParentChange) { + if (e->type() == QEvent::ParentChange) { // if we've reparented a window that has the current context // bound, we need to rebind that context to the new window id if (d->glcx == QGLContext::currentContext()) @@ -5149,24 +5128,24 @@ void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QM #endif #ifndef QT_OPENGL_ES_1 -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_gl_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_gl_engine) #endif Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() { #if defined(QT_OPENGL_ES_1) - return qt_gl_engine(); + return qt_gl_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); else - return qt_gl_engine(); + return qt_gl_engine()->engine(); #endif } @@ -5431,13 +5410,23 @@ void QGLContextGroup::removeShare(const QGLContext *context) { group->m_shares.clear(); } -QGLContextResource::QGLContextResource(FreeFunc f) - : free(f), active(0) +QGLContextGroupResourceBase::QGLContextGroupResourceBase() + : active(0) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Creating context group resource object %p.", this); +#endif } -QGLContextResource::~QGLContextResource() +QGLContextGroupResourceBase::~QGLContextGroupResourceBase() { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size()); +#endif + for (int i = 0; i < m_groups.size(); ++i) { + m_groups.at(i)->m_resources.remove(this); + active.deref(); + } #ifndef QT_NO_DEBUG if (active != 0) { qWarning("QtOpenGL: Resources are still available at program shutdown.\n" @@ -5447,37 +5436,47 @@ QGLContextResource::~QGLContextResource() #endif } -void QGLContextResource::insert(const QGLContext *key, void *value) +void QGLContextGroupResourceBase::insert(const QGLContext *context, void *value) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this); +#endif + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); Q_ASSERT(!group->m_resources.contains(this)); group->m_resources.insert(this, value); + m_groups.append(group); active.ref(); } -void *QGLContextResource::value(const QGLContext *key) +void *QGLContextGroupResourceBase::value(const QGLContext *context) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); return group->m_resources.value(this, 0); } -void QGLContextResource::cleanup(const QGLContext *ctx, void *value) +void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread()); +#endif QGLShareContextScope scope(ctx); - free(value); + freeResource(value); active.deref(); + + QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); + m_groups.removeOne(group); } -void QGLContextGroup::cleanupResources(const QGLContext *ctx) +void QGLContextGroup::cleanupResources(const QGLContext *context) { // If there are still shares, then no cleanup to be done yet. if (m_shares.size() > 1) return; // Iterate over all resources and free each in turn. - QHash<QGLContextResource *, void *>::ConstIterator it; + QHash<QGLContextGroupResourceBase *, void *>::ConstIterator it; for (it = m_resources.begin(); it != m_resources.end(); ++it) - it.key()->cleanup(ctx, it.value()); + it.key()->cleanup(context, it.value()); } QGLSharedResourceGuard::~QGLSharedResourceGuard() diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f85cad5..2ac4cb6 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -56,7 +56,6 @@ QT_BEGIN_HEADER #if defined(Q_WS_MAC) # include <OpenGL/gl.h> -# include <OpenGL/glu.h> #elif defined(QT_OPENGL_ES_1) # include <GLES/gl.h> #ifndef GL_DOUBLE @@ -75,9 +74,6 @@ typedef GLfloat GLdouble; #endif #else # include <GL/gl.h> -# ifndef QT_LINUXBASE -# include <GL/glu.h> -# endif #endif QT_BEGIN_NAMESPACE @@ -424,6 +420,7 @@ private: friend class QGLPixmapData; friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; + friend struct QGLGlyphTexture; friend class QGLContextGroup; friend class QGLSharedResourceGuard; friend class QGLPixmapBlurFilter; @@ -443,6 +440,7 @@ private: friend class QGLWidgetGLPaintDevice; friend class QX11GLPixmapData; friend class QX11GLSharedContexts; + friend class QGLContextResourceBase; private: Q_DISABLE_COPY(QGLContext) }; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 387c8f7..f86a848 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -217,11 +217,9 @@ public: #endif }; -class QGLContextResource; +class QGLContextGroupResourceBase; class QGLSharedResourceGuard; -typedef QHash<QString, GLuint> QGLDDSCache; - // QGLContextPrivate has the responsibility of creating context groups. // QGLContextPrivate maintains the reference counter and destroys // context groups when needed. @@ -240,22 +238,22 @@ public: static void addShare(const QGLContext *context, const QGLContext *share); static void removeShare(const QGLContext *context); + private: QGLContextGroup(const QGLContext *context); QGLExtensionFuncs m_extensionFuncs; const QGLContext *m_context; // context group's representative QList<const QGLContext *> m_shares; - QHash<QGLContextResource *, void *> m_resources; + QHash<QGLContextGroupResourceBase *, void *> m_resources; QGLSharedResourceGuard *m_guards; // double-linked list of active guards. QAtomicInt m_refs; - QGLDDSCache m_dds_cache; void cleanupResources(const QGLContext *ctx); friend class QGLContext; friend class QGLContextPrivate; - friend class QGLContextResource; + friend class QGLContextGroupResourceBase; }; // Get the context that resources for "ctx" will transfer to once @@ -320,6 +318,8 @@ class QGLTexture; // all the GL2 engine uses: #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3 +class QGLContextResourceBase; + class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) @@ -355,6 +355,7 @@ public: QGLCmap* cmap; HBITMAP hbitmap; HDC hbitmap_hdc; + Qt::HANDLE threadId; #endif #ifndef QT_NO_EGL uint ownsEglContext : 1; @@ -415,6 +416,7 @@ public: GLuint current_fbo; GLuint default_fbo; QPaintEngine *active_engine; + QHash<QGLContextResourceBase *, void *> m_resources; bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; @@ -425,7 +427,7 @@ public: #endif #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) - static QGLExtensionFuncs qt_extensionFuncs; + static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs; static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *); #endif @@ -623,24 +625,130 @@ inline GLenum qt_gl_preferredTextureTarget() #endif } -// One resource per group of shared contexts. -class Q_OPENGL_EXPORT QGLContextResource +/* + Base for resources that are shared in a context group. +*/ +class Q_OPENGL_EXPORT QGLContextGroupResourceBase { public: - typedef void (*FreeFunc)(void *); - QGLContextResource(FreeFunc f); - ~QGLContextResource(); - // Set resource 'value' for 'key' and all its shared contexts. - void insert(const QGLContext *key, void *value); - // Return resource for 'key' or a shared context. - void *value(const QGLContext *key); - // Cleanup 'value' in response to a context group being destroyed. - void cleanup(const QGLContext *ctx, void *value); + QGLContextGroupResourceBase(); + virtual ~QGLContextGroupResourceBase(); + void insert(const QGLContext *context, void *value); + void *value(const QGLContext *context); + void cleanup(const QGLContext *context, void *value); + virtual void freeResource(void *value) = 0; + +protected: + QList<QGLContextGroup *> m_groups; + private: - FreeFunc free; QAtomicInt active; }; +/* + The QGLContextGroupResource template is used to manage a resource + for a group of sharing GL contexts. When the last context in the + group is destroyed, or when the QGLContextGroupResource object + itself is destroyed (implies potential context switches), the + resource will be freed. + + The class used as the template class type needs to have a + constructor with the following signature: + T(const QGLContext *); +*/ +template <class T> +class QGLContextGroupResource : public QGLContextGroupResourceBase +{ +public: + ~QGLContextGroupResource() { + for (int i = 0; i < m_groups.size(); ++i) { + const QGLContext *context = m_groups.at(i)->context(); + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + +/* + Base for resources that are context specific. +*/ +class Q_OPENGL_EXPORT QGLContextResourceBase +{ +public: + virtual ~QGLContextResourceBase() { + for (int i = 0; i < m_contexts.size(); ++i) + m_contexts.at(i)->d_ptr->m_resources.remove(this); + } + + void insert(const QGLContext *context, void *value) { + context->d_ptr->m_resources.insert(this, value); + } + + void *value(const QGLContext *context) { + return context->d_ptr->m_resources.value(this, 0); + } + virtual void freeResource(void *value) = 0; + +protected: + QList<const QGLContext *> m_contexts; +}; + +/* + The QGLContextResource template is used to manage a resource for a + single GL context. Just before the context is destroyed (while it's + still the current context), or when the QGLContextResource object + itself is destroyed (implies potential context switches), the + resource will be freed. The class used as the template class type + needs to have a constructor with the following signature: T(const + QGLContext *); +*/ +template <class T> +class QGLContextResource : public QGLContextResourceBase +{ +public: + ~QGLContextResource() { + for (int i = 0; i < m_contexts.size(); ++i) { + const QGLContext *context = m_contexts.at(i); + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + // Put a guard around a GL object identifier and its context. // When the context goes away, a shared context will be used // in its place. If there are no more shared contexts, then @@ -730,6 +838,24 @@ private: int gl_extensions_length; }; + +// this is a class that wraps a QThreadStorage object for storing +// thread local instances of the GL 1 and GL 2 paint engines + +template <class T> +class QGLEngineThreadStorage +{ +public: + QPaintEngine *engine() { + QPaintEngine *&localEngine = storage.localData(); + if (!localEngine) + localEngine = new T; + return localEngine; + } + +private: + QThreadStorage<QPaintEngine *> storage; +}; QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 5ab944a..3f13ac4 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -1261,6 +1261,7 @@ void QGLContext::reset() } d->dc = 0; d->win = 0; + d->threadId = 0; d->pixelFormatId = 0; d->sharing = false; d->valid = false; @@ -1283,8 +1284,9 @@ void QGLContext::makeCurrent() if (d->rc == wglGetCurrentContext() || !d->valid) // already current return; - if (d->win) { + if (d->win && (!d->dc || d->threadId != QThread::currentThreadId())) { d->dc = GetDC(d->win); + d->threadId = QThread::currentThreadId(); if (!d->dc) { qwglError("QGLContext::makeCurrent()", "GetDC()"); return; @@ -1322,6 +1324,7 @@ void QGLContext::doneCurrent() if (d->win && d->dc) { ReleaseDC(d->win, d->dc); d->dc = 0; + d->threadId = 0; } } diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 6259cca..6d7449d 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -872,10 +872,10 @@ struct QGLExtensionFuncs #endif extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); -bool qt_resolve_buffer_extensions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx); bool qt_resolve_version_1_3_functions(QGLContext *ctx); -bool qt_resolve_version_2_0_functions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_version_2_0_functions(QGLContext *ctx); bool qt_resolve_stencil_face_extension(QGLContext *ctx); bool qt_resolve_frag_program_extensions(QGLContext *ctx); diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 9b8a3d1..876e97a 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -984,11 +984,11 @@ QImage QGLFramebufferObject::toImage() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ @@ -1002,7 +1002,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #if !defined (QT_OPENGL_ES_2) if (qt_gl_preferGL2Engine()) { #endif - QPaintEngine *engine = qt_buffer_2_engine(); + QPaintEngine *engine = qt_buffer_2_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QGL2PaintEngineEx; return d->engine; @@ -1014,7 +1014,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #endif #if !defined(QT_OPENGL_ES_2) - QPaintEngine *engine = qt_buffer_engine(); + QPaintEngine *engine = qt_buffer_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QOpenGLPaintEngine; return d->engine; diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp new file mode 100644 index 0000000..8a544c1 --- /dev/null +++ b/src/opengl/qglfunctions.cpp @@ -0,0 +1,3705 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglfunctions.h" +#include "qgl_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGLFunctions + \brief The QGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API. + \since 4.8 + \ingroup painting-3D + + OpenGL/ES 2.0 defines a subset of the OpenGL specification that is + common across many desktop and embedded OpenGL implementations. + However, it can be difficult to use the functions from that subset + because they need to be resolved manually on desktop systems. + + QGLFunctions provides a guaranteed API that is available on all + OpenGL systems and takes care of function resolution on systems + that need it. The recommended way to use QGLFunctions is by + direct inheritance: + + \code + class MyGLWidget : public QGLWidget, protected QGLFunctions + { + Q_OBJECT + public: + MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {} + + protected: + void initializeGL(); + void paintGL(); + }; + + void MyGLWidget::initializeGL() + { + initializeGLFunctions(); + } + \endcode + + The \c{paintGL()} function can then use any of the OpenGL/ES 2.0 + functions without explicit resolution, such as glActiveTexture() + in the following example: + + \code + void MyGLWidget::paintGL() + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textureId); + ... + } + \endcode + + QGLFunctions can also be used directly for ad-hoc invocation + of OpenGL/ES 2.0 functions on all platforms: + + \code + QGLFunctions glFuncs(QGLContext::currentContext()); + glFuncs.glActiveTexture(GL_TEXTURE1); + \endcode + + QGLFunctions provides wrappers for all OpenGL/ES 2.0 functions, + except those like \c{glDrawArrays()}, \c{glViewport()}, and + \c{glBindTexture()} that don't have portability issues. + + Including the header for QGLFunctions will also define all of + the OpenGL/ES 2.0 macro constants that are not already defined by + the system's OpenGL headers, such as \c{GL_TEXTURE1} above. + + The hasOpenGLFeature() and openGLFeatures() functions can be used + to determine if the OpenGL implementation has a major OpenGL/ES 2.0 + feature. For example, the following checks if non power of two + textures are available: + + \code + QGLFunctions funcs(QGLContext::currentContext()); + bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures); + \endcode +*/ + +/*! + \enum QGLFunctions::OpenGLFeature + This enum defines OpenGL/ES 2.0 features that may be optional + on other platforms. + + \value Multitexture glActiveTexture() function is available. + \value Shaders Shader functions are available. + \value Buffers Vertex and index buffer functions are available. + \value Framebuffers Framebuffer object functions are available. + \value BlendColor glBlendColor() is available. + \value BlendEquation glBlendEquation() is available. + \value BlendEquationSeparate glBlendEquationSeparate() is available. + \value BlendFuncSeparate glBlendFuncSeparate() is available. + \value BlendSubtract Blend subtract mode is available. + \value CompressedTextures Compressed texture functions are available. + \value Multisample glSampleCoverage() function is available. + \value StencilSeparate Separate stencil functions are available. + \value NPOTTextures Non power of two textures are available. +*/ + +// Hidden private fields for additional extension data. +struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate +{ + QGLFunctionsPrivateEx(const QGLContext *context = 0) + : QGLFunctionsPrivate(context) + , m_features(-1) {} + + int m_features; +}; + +#if QT_VERSION >= 0x040800 +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLFunctionsPrivateEx>, qt_gl_functions_resource) +#else +static void qt_gl_functions_free(void *data) +{ + delete reinterpret_cast<QGLFunctionsPrivateEx *>(data); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gl_functions_resource, (qt_gl_functions_free)) +#endif +static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0) +{ + if (!context) + context = QGLContext::currentContext(); + Q_ASSERT(context); + QGLFunctionsPrivateEx *funcs = + reinterpret_cast<QGLFunctionsPrivateEx *> + (qt_gl_functions_resource()->value(context)); +#if QT_VERSION < 0x040800 + if (!funcs) { + funcs = new QGLFunctionsPrivateEx(); + qt_gl_functions_resource()->insert(context, funcs); + } +#endif + return funcs; +} + +/*! + Constructs a default function resolver. The resolver cannot + be used until initializeGLFunctions() is called to specify + the context. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions() + : d_ptr(0) +{ +} + +/*! + Constructs a function resolver for \a context. If \a context + is null, then the resolver will be created for the current QGLContext. + + An object constructed in this way can only be used with \a context + and other contexts that share with it. Use initializeGLFunctions() + to change the object's context association. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions(const QGLContext *context) + : d_ptr(qt_gl_functions(context)) +{ +} + +/*! + \fn QGLFunctions::~QGLFunctions() + + Destroys this function resolver. +*/ + +static int qt_gl_resolve_features() +{ +#if defined(QT_OPENGL_ES_2) + return QGLFunctions::Multitexture | + QGLFunctions::Shaders | + QGLFunctions::Buffers | + QGLFunctions::Framebuffers | + QGLFunctions::BlendColor | + QGLFunctions::BlendEquation | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::BlendFuncSeparate | + QGLFunctions::BlendSubtract | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample | + QGLFunctions::StencilSeparate | + QGLFunctions::NPOTTextures; +#elif defined(QT_OPENGL_ES) + int features = QGLFunctions::Multitexture | + QGLFunctions::Buffers | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + if (extensions.match("GL_OES_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_OES_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_OES_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_OES_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_OES_texture_npot")) + features |= QGLFunctions::NPOTTextures; + return features; +#else + int features = 0; + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + + // Recognize features by extension name. + if (extensions.match("GL_ARB_multitexture")) + features |= QGLFunctions::Multitexture; + if (extensions.match("GL_ARB_shader_objects")) + features |= QGLFunctions::Shaders; + if (extensions.match("GL_EXT_framebuffer_object") || + extensions.match("GL_ARB_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_EXT_blend_color")) + features |= QGLFunctions::BlendColor; + if (extensions.match("GL_EXT_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_EXT_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_EXT_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_ARB_texture_compression")) + features |= QGLFunctions::CompressedTextures; + if (extensions.match("GL_ARB_multisample")) + features |= QGLFunctions::Multisample; + if (extensions.match("GL_ARB_texture_non_power_of_two")) + features |= QGLFunctions::NPOTTextures; + + // Recognize features by minimum OpenGL version. + if (versions & QGLFormat::OpenGL_Version_1_2) { + features |= QGLFunctions::BlendColor | + QGLFunctions::BlendEquation; + } + if (versions & QGLFormat::OpenGL_Version_1_3) { + features |= QGLFunctions::Multitexture | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + } + if (versions & QGLFormat::OpenGL_Version_1_4) + features |= QGLFunctions::BlendFuncSeparate; + if (versions & QGLFormat::OpenGL_Version_1_5) + features |= QGLFunctions::Buffers; + if (versions & QGLFormat::OpenGL_Version_2_0) { + features |= QGLFunctions::Shaders | + QGLFunctions::StencilSeparate | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::NPOTTextures; + } + return features; +#endif +} + +/*! + Returns the set of features that are present on this system's + OpenGL implementation. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa hasOpenGLFeature() +*/ +QGLFunctions::OpenGLFeatures QGLFunctions::openGLFeatures() const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return 0; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return QGLFunctions::OpenGLFeatures(d->m_features); +} + +/*! + Returns true if \a feature is present on this system's OpenGL + implementation; false otherwise. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa openGLFeatures() +*/ +bool QGLFunctions::hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return false; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return (d->m_features & int(feature)) != 0; +} + +/*! + Initializes GL function resolution for \a context. If \a context + is null, then the current QGLContext will be used. + + After calling this function, the QGLFunctions object can only be + used with \a context and other contexts that share with it. + Call initializeGLFunctions() again to change the object's context + association. +*/ +void QGLFunctions::initializeGLFunctions(const QGLContext *context) +{ + d_ptr = qt_gl_functions(context); +} + +/*! + \fn void QGLFunctions::glActiveTexture(GLenum texture) + + Convenience function that calls glActiveTexture(\a texture). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}. +*/ + +/*! + \fn void QGLFunctions::glAttachShader(GLuint program, GLuint shader) + + Convenience function that calls glAttachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) + + Convenience function that calls glBindAttribLocation(\a program, \a index, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) + + Convenience function that calls glBindBuffer(\a target, \a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) + + Convenience function that calls glBindFramebuffer(\a target, \a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) + + Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) + + Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquation(GLenum mode) + + Convenience function that calls glBlendEquation(\a mode). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) + + Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) + + Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) + + Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}. +*/ + +/*! + \fn void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) + + Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}. +*/ + +/*! + \fn GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) + + Convenience function that calls glCheckFramebufferStatus(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}. +*/ + +/*! + \fn void QGLFunctions::glClearDepthf(GLclampf depth) + + Convenience function that calls glClearDepth(\a depth) on + desktop OpenGL systems and glClearDepthf(\a depth) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}. +*/ + +/*! + \fn void QGLFunctions::glCompileShader(GLuint shader) + + Convenience function that calls glCompileShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateProgram() + + Convenience function that calls glCreateProgram(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateShader(GLenum type) + + Convenience function that calls glCreateShader(\a type). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) + + Convenience function that calls glDeleteBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) + + Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteProgram(GLuint program) + + Convenience function that calls glDeleteProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) + + Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteShader(GLuint shader) + + Convenience function that calls glDeleteShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) + + Convenience function that calls glDepthRange(\a zNear, \a zFar) on + desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}. +*/ + +/*! + \fn void QGLFunctions::glDetachShader(GLuint program, GLuint shader) + + Convenience function that calls glDetachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDisableVertexAttribArray(GLuint index) + + Convenience function that calls glDisableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glEnableVertexAttribArray(GLuint index) + + Convenience function that calls glEnableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + + Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + + Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}. +*/ + +/*! + \fn void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) + + Convenience function that calls glGenBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenerateMipmap(GLenum target) + + Convenience function that calls glGenerateMipmap(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}. +*/ + +/*! + \fn void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) + + Convenience function that calls glGenFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) + + Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) + + Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) + + Convenience function that calls glGetAttribLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) + + Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) + + Convenience function that calls glGetProgramiv(\a program, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) + + Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) + + Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) + + Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) + + Convenience function that calls glGetUniformfv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) + + Convenience function that calls glGetUniformiv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) + + Convenience function that calls glGetUniformLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) + + Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) + + Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) + + Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsBuffer(GLuint buffer) + + Convenience function that calls glIsBuffer(\a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) + + Convenience function that calls glIsFramebuffer(\a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsProgram(GLuint program) + + Convenience function that calls glIsProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) + + Convenience function that calls glIsRenderbuffer(\a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsShader(GLuint shader) + + Convenience function that calls glIsShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glLinkProgram(GLuint program) + + Convenience function that calls glLinkProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glReleaseShaderCompiler() + + Convenience function that calls glReleaseShaderCompiler(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + + Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}. +*/ + +/*! + \fn void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) + + Convenience function that calls glSampleCoverage(\a value, \a invert). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}. +*/ + +/*! + \fn void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) + + Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) + + Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) + + Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) + + Convenience function that calls glStencilMaskSeparate(\a face, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) + + Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glUniform1f(GLint location, GLfloat x) + + Convenience function that calls glUniform1f(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform1fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1i(GLint location, GLint x) + + Convenience function that calls glUniform1i(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform1iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) + + Convenience function that calls glUniform2f(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform2fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) + + Convenience function that calls glUniform2i(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform2iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform3fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) + + Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform3iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform4fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) + + Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform4iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUseProgram(GLuint program) + + Convenience function that calls glUseProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glValidateProgram(GLuint program) + + Convenience function that calls glValidateProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) + + Convenience function that calls glVertexAttrib1f(\a indx, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib1fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) + + Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib2fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib3fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib4fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) + + Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +#ifndef QT_OPENGL_ES_2 + +static void qglfResolveActiveTexture(GLenum texture) +{ + typedef void (QGLF_APIENTRYP type_glActiveTexture)(GLenum texture); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTexture")); + if (!funcs->activeTexture) { + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTextureARB")); + } + + if (funcs->activeTexture) + funcs->activeTexture(texture); + else + funcs->activeTexture = qglfResolveActiveTexture; +} + +static void qglfResolveAttachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glAttachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachShader")); + if (!funcs->attachShader) { + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachObjectARB")); + } + + if (funcs->attachShader) + funcs->attachShader(program, shader); + else + funcs->attachShader = qglfResolveAttachShader; +} + +static void qglfResolveBindAttribLocation(GLuint program, GLuint index, const char* name) +{ + typedef void (QGLF_APIENTRYP type_glBindAttribLocation)(GLuint program, GLuint index, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocation")); + if (!funcs->bindAttribLocation) { + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocationARB")); + } + + if (funcs->bindAttribLocation) + funcs->bindAttribLocation(program, index, name); + else + funcs->bindAttribLocation = qglfResolveBindAttribLocation; +} + +static void qglfResolveBindBuffer(GLenum target, GLuint buffer) +{ + typedef void (QGLF_APIENTRYP type_glBindBuffer)(GLenum target, GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferOES")); + } +#endif + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferEXT")); + } + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferARB")); + } + + if (funcs->bindBuffer) + funcs->bindBuffer(target, buffer); + else + funcs->bindBuffer = qglfResolveBindBuffer; +} + +static void qglfResolveBindFramebuffer(GLenum target, GLuint framebuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindFramebuffer)(GLenum target, GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferOES")); + } +#endif + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferEXT")); + } + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferARB")); + } + + if (funcs->bindFramebuffer) + funcs->bindFramebuffer(target, framebuffer); + else + funcs->bindFramebuffer = qglfResolveBindFramebuffer; +} + +static void qglfResolveBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindRenderbuffer)(GLenum target, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferOES")); + } +#endif + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferEXT")); + } + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferARB")); + } + + if (funcs->bindRenderbuffer) + funcs->bindRenderbuffer(target, renderbuffer); + else + funcs->bindRenderbuffer = qglfResolveBindRenderbuffer; +} + +static void qglfResolveBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColor")); +#ifdef QT_OPENGL_ES + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorOES")); + } +#endif + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorEXT")); + } + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorARB")); + } + + if (funcs->blendColor) + funcs->blendColor(red, green, blue, alpha); + else + funcs->blendColor = qglfResolveBlendColor; +} + +static void qglfResolveBlendEquation(GLenum mode) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquation)(GLenum mode); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquation")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationOES")); + } +#endif + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationEXT")); + } + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationARB")); + } + + if (funcs->blendEquation) + funcs->blendEquation(mode); + else + funcs->blendEquation = qglfResolveBlendEquation; +} + +static void qglfResolveBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateOES")); + } +#endif + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateEXT")); + } + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateARB")); + } + + if (funcs->blendEquationSeparate) + funcs->blendEquationSeparate(modeRGB, modeAlpha); + else + funcs->blendEquationSeparate = qglfResolveBlendEquationSeparate; +} + +static void qglfResolveBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateOES")); + } +#endif + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateEXT")); + } + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateARB")); + } + + if (funcs->blendFuncSeparate) + funcs->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + else + funcs->blendFuncSeparate = qglfResolveBlendFuncSeparate; +} + +static void qglfResolveBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ + typedef void (QGLF_APIENTRYP type_glBufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataOES")); + } +#endif + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataEXT")); + } + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataARB")); + } + + if (funcs->bufferData) + funcs->bufferData(target, size, data, usage); + else + funcs->bufferData = qglfResolveBufferData; +} + +static void qglfResolveBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glBufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataOES")); + } +#endif + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataEXT")); + } + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataARB")); + } + + if (funcs->bufferSubData) + funcs->bufferSubData(target, offset, size, data); + else + funcs->bufferSubData = qglfResolveBufferSubData; +} + +static GLenum qglfResolveCheckFramebufferStatus(GLenum target) +{ + typedef GLenum (QGLF_APIENTRYP type_glCheckFramebufferStatus)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatus")); +#ifdef QT_OPENGL_ES + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusOES")); + } +#endif + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT")); + } + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusARB")); + } + + if (funcs->checkFramebufferStatus) + return funcs->checkFramebufferStatus(target); + funcs->checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + return GLenum(0); +} + +static void qglfResolveCompileShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glCompileShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + if (!funcs->compileShader) { + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + } + + if (funcs->compileShader) + funcs->compileShader(shader); + else + funcs->compileShader = qglfResolveCompileShader; +} + +static void qglfResolveCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DOES")); + } +#endif + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DEXT")); + } + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); + } + + if (funcs->compressedTexImage2D) + funcs->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); + else + funcs->compressedTexImage2D = qglfResolveCompressedTexImage2D; +} + +static void qglfResolveCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DOES")); + } +#endif + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DEXT")); + } + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DARB")); + } + + if (funcs->compressedTexSubImage2D) + funcs->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); + else + funcs->compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; +} + +static GLuint qglfResolveCreateProgram() +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateProgram)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgram")); + if (!funcs->createProgram) { + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgramObjectARB")); + } + + if (funcs->createProgram) + return funcs->createProgram(); + funcs->createProgram = qglfResolveCreateProgram; + return GLuint(0); +} + +static GLuint qglfResolveCreateShader(GLenum type) +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateShader)(GLenum type); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShader")); + if (!funcs->createShader) { + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShaderObjectARB")); + } + + if (funcs->createShader) + return funcs->createShader(type); + funcs->createShader = qglfResolveCreateShader; + return GLuint(0); +} + +static void qglfResolveDeleteBuffers(GLsizei n, const GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteBuffers)(GLsizei n, const GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersOES")); + } +#endif + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersEXT")); + } + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersARB")); + } + + if (funcs->deleteBuffers) + funcs->deleteBuffers(n, buffers); + else + funcs->deleteBuffers = qglfResolveDeleteBuffers; +} + +static void qglfResolveDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersOES")); + } +#endif + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersEXT")); + } + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersARB")); + } + + if (funcs->deleteFramebuffers) + funcs->deleteFramebuffers(n, framebuffers); + else + funcs->deleteFramebuffers = qglfResolveDeleteFramebuffers; +} + +static void qglfResolveDeleteProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glDeleteProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteProgram")); + if (!funcs->deleteProgram) { + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteProgram) + funcs->deleteProgram(program); + else + funcs->deleteProgram = qglfResolveDeleteProgram; +} + +static void qglfResolveDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersOES")); + } +#endif + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT")); + } + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersARB")); + } + + if (funcs->deleteRenderbuffers) + funcs->deleteRenderbuffers(n, renderbuffers); + else + funcs->deleteRenderbuffers = qglfResolveDeleteRenderbuffers; +} + +static void qglfResolveDeleteShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDeleteShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteShader")); + if (!funcs->deleteShader) { + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteShader) + funcs->deleteShader(shader); + else + funcs->deleteShader = qglfResolveDeleteShader; +} + +static void qglfResolveDetachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDetachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachShader")); + if (!funcs->detachShader) { + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachObjectARB")); + } + + if (funcs->detachShader) + funcs->detachShader(program, shader); + else + funcs->detachShader = qglfResolveDetachShader; +} + +static void qglfResolveDisableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glDisableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArray")); + if (!funcs->disableVertexAttribArray) { + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB")); + } + + if (funcs->disableVertexAttribArray) + funcs->disableVertexAttribArray(index); + else + funcs->disableVertexAttribArray = qglfResolveDisableVertexAttribArray; +} + +static void qglfResolveEnableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glEnableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArray")); + if (!funcs->enableVertexAttribArray) { + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB")); + } + + if (funcs->enableVertexAttribArray) + funcs->enableVertexAttribArray(index); + else + funcs->enableVertexAttribArray = qglfResolveEnableVertexAttribArray; +} + +static void qglfResolveFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferOES")); + } +#endif + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT")); + } + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferARB")); + } + + if (funcs->framebufferRenderbuffer) + funcs->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); + else + funcs->framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; +} + +static void qglfResolveFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2D")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DOES")); + } +#endif + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DEXT")); + } + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DARB")); + } + + if (funcs->framebufferTexture2D) + funcs->framebufferTexture2D(target, attachment, textarget, texture, level); + else + funcs->framebufferTexture2D = qglfResolveFramebufferTexture2D; +} + +static void qglfResolveGenBuffers(GLsizei n, GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glGenBuffers)(GLsizei n, GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersOES")); + } +#endif + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersEXT")); + } + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersARB")); + } + + if (funcs->genBuffers) + funcs->genBuffers(n, buffers); + else + funcs->genBuffers = qglfResolveGenBuffers; +} + +static void qglfResolveGenerateMipmap(GLenum target) +{ + typedef void (QGLF_APIENTRYP type_glGenerateMipmap)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmap")); +#ifdef QT_OPENGL_ES + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapOES")); + } +#endif + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapEXT")); + } + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapARB")); + } + + if (funcs->generateMipmap) + funcs->generateMipmap(target); + else + funcs->generateMipmap = qglfResolveGenerateMipmap; +} + +static void qglfResolveGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenFramebuffers)(GLsizei n, GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersOES")); + } +#endif + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersEXT")); + } + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersARB")); + } + + if (funcs->genFramebuffers) + funcs->genFramebuffers(n, framebuffers); + else + funcs->genFramebuffers = qglfResolveGenFramebuffers; +} + +static void qglfResolveGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersOES")); + } +#endif + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersEXT")); + } + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersARB")); + } + + if (funcs->genRenderbuffers) + funcs->genRenderbuffers(n, renderbuffers); + else + funcs->genRenderbuffers = qglfResolveGenRenderbuffers; +} + +static void qglfResolveGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttrib")); + if (!funcs->getActiveAttrib) { + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttribARB")); + } + + if (funcs->getActiveAttrib) + funcs->getActiveAttrib(program, index, bufsize, length, size, type, name); + else + funcs->getActiveAttrib = qglfResolveGetActiveAttrib; +} + +static void qglfResolveGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniform")); + if (!funcs->getActiveUniform) { + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniformARB")); + } + + if (funcs->getActiveUniform) + funcs->getActiveUniform(program, index, bufsize, length, size, type, name); + else + funcs->getActiveUniform = qglfResolveGetActiveUniform; +} + +static void qglfResolveGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + typedef void (QGLF_APIENTRYP type_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedShaders")); + if (!funcs->getAttachedShaders) { + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedObjectsARB")); + } + + if (funcs->getAttachedShaders) + funcs->getAttachedShaders(program, maxcount, count, shaders); + else + funcs->getAttachedShaders = qglfResolveGetAttachedShaders; +} + +static int qglfResolveGetAttribLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetAttribLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocation")); + if (!funcs->getAttribLocation) { + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocationARB")); + } + + if (funcs->getAttribLocation) + return funcs->getAttribLocation(program, name); + funcs->getAttribLocation = qglfResolveGetAttribLocation; + return int(0); +} + +static void qglfResolveGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivOES")); + } +#endif + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivEXT")); + } + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivARB")); + } + + if (funcs->getBufferParameteriv) + funcs->getBufferParameteriv(target, pname, params); + else + funcs->getBufferParameteriv = qglfResolveGetBufferParameteriv; +} + +static void qglfResolveGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivOES")); + } +#endif + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT")); + } + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivARB")); + } + + if (funcs->getFramebufferAttachmentParameteriv) + funcs->getFramebufferAttachmentParameteriv(target, attachment, pname, params); + else + funcs->getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; +} + +static void qglfResolveGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramiv)(GLuint program, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetProgramiv")); + if (!funcs->getProgramiv) { + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getProgramiv) + funcs->getProgramiv(program, pname, params); + else + funcs->getProgramiv = qglfResolveGetProgramiv; +} + +static void qglfResolveGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetProgramInfoLog")); + if (!funcs->getProgramInfoLog) { + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getProgramInfoLog) + funcs->getProgramInfoLog(program, bufsize, length, infolog); + else + funcs->getProgramInfoLog = qglfResolveGetProgramInfoLog; +} + +static void qglfResolveGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivOES")); + } +#endif + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT")); + } + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivARB")); + } + + if (funcs->getRenderbufferParameteriv) + funcs->getRenderbufferParameteriv(target, pname, params); + else + funcs->getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; +} + +static void qglfResolveGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetShaderiv")); + if (!funcs->getShaderiv) { + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getShaderiv) + funcs->getShaderiv(shader, pname, params); + else + funcs->getShaderiv = qglfResolveGetShaderiv; +} + +static void qglfResolveGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetShaderInfoLog")); + if (!funcs->getShaderInfoLog) { + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getShaderInfoLog) + funcs->getShaderInfoLog(shader, bufsize, length, infolog); + else + funcs->getShaderInfoLog = qglfResolveGetShaderInfoLog; +} + +static void qglfSpecialGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + Q_UNUSED(shadertype); + Q_UNUSED(precisiontype); + range[0] = range[1] = precision[0] = 0; +} + +static void qglfResolveGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormat")); +#ifdef QT_OPENGL_ES + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatOES")); + } +#endif + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatEXT")); + } + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatARB")); + } + + if (!funcs->getShaderPrecisionFormat) + funcs->getShaderPrecisionFormat = qglfSpecialGetShaderPrecisionFormat; + + funcs->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +} + +static void qglfResolveGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSource")); + if (!funcs->getShaderSource) { + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSourceARB")); + } + + if (funcs->getShaderSource) + funcs->getShaderSource(shader, bufsize, length, source); + else + funcs->getShaderSource = qglfResolveGetShaderSource; +} + +static void qglfResolveGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformfv)(GLuint program, GLint location, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfv")); + if (!funcs->getUniformfv) { + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfvARB")); + } + + if (funcs->getUniformfv) + funcs->getUniformfv(program, location, params); + else + funcs->getUniformfv = qglfResolveGetUniformfv; +} + +static void qglfResolveGetUniformiv(GLuint program, GLint location, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformiv)(GLuint program, GLint location, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformiv")); + if (!funcs->getUniformiv) { + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformivARB")); + } + + if (funcs->getUniformiv) + funcs->getUniformiv(program, location, params); + else + funcs->getUniformiv = qglfResolveGetUniformiv; +} + +static int qglfResolveGetUniformLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetUniformLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocation")); + if (!funcs->getUniformLocation) { + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocationARB")); + } + + if (funcs->getUniformLocation) + return funcs->getUniformLocation(program, name); + funcs->getUniformLocation = qglfResolveGetUniformLocation; + return int(0); +} + +static void qglfResolveGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfv")); + if (!funcs->getVertexAttribfv) { + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfvARB")); + } + + if (funcs->getVertexAttribfv) + funcs->getVertexAttribfv(index, pname, params); + else + funcs->getVertexAttribfv = qglfResolveGetVertexAttribfv; +} + +static void qglfResolveGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribiv")); + if (!funcs->getVertexAttribiv) { + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribivARB")); + } + + if (funcs->getVertexAttribiv) + funcs->getVertexAttribiv(index, pname, params); + else + funcs->getVertexAttribiv = qglfResolveGetVertexAttribiv; +} + +static void qglfResolveGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointerv")); + if (!funcs->getVertexAttribPointerv) { + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointervARB")); + } + + if (funcs->getVertexAttribPointerv) + funcs->getVertexAttribPointerv(index, pname, pointer); + else + funcs->getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; +} + +static GLboolean qglfResolveIsBuffer(GLuint buffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsBuffer)(GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferOES")); + } +#endif + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferEXT")); + } + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferARB")); + } + + if (funcs->isBuffer) + return funcs->isBuffer(buffer); + funcs->isBuffer = qglfResolveIsBuffer; + return GLboolean(0); +} + +static GLboolean qglfResolveIsFramebuffer(GLuint framebuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsFramebuffer)(GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferOES")); + } +#endif + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferEXT")); + } + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferARB")); + } + + if (funcs->isFramebuffer) + return funcs->isFramebuffer(framebuffer); + funcs->isFramebuffer = qglfResolveIsFramebuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsProgram(GLuint program) +{ + return program != 0; +} + +static GLboolean qglfResolveIsProgram(GLuint program) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgram")); + if (!funcs->isProgram) { + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgramARB")); + } + + if (!funcs->isProgram) + funcs->isProgram = qglfSpecialIsProgram; + + return funcs->isProgram(program); +} + +static GLboolean qglfResolveIsRenderbuffer(GLuint renderbuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsRenderbuffer)(GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferOES")); + } +#endif + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferEXT")); + } + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferARB")); + } + + if (funcs->isRenderbuffer) + return funcs->isRenderbuffer(renderbuffer); + funcs->isRenderbuffer = qglfResolveIsRenderbuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsShader(GLuint shader) +{ + return shader != 0; +} + +static GLboolean qglfResolveIsShader(GLuint shader) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShader")); + if (!funcs->isShader) { + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShaderARB")); + } + + if (!funcs->isShader) + funcs->isShader = qglfSpecialIsShader; + + return funcs->isShader(shader); +} + +static void qglfResolveLinkProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glLinkProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgram")); + if (!funcs->linkProgram) { + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgramARB")); + } + + if (funcs->linkProgram) + funcs->linkProgram(program); + else + funcs->linkProgram = qglfResolveLinkProgram; +} + +static void qglfSpecialReleaseShaderCompiler() +{ +} + +static void qglfResolveReleaseShaderCompiler() +{ + typedef void (QGLF_APIENTRYP type_glReleaseShaderCompiler)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompiler")); + if (!funcs->releaseShaderCompiler) { + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompilerARB")); + } + + if (!funcs->releaseShaderCompiler) + funcs->releaseShaderCompiler = qglfSpecialReleaseShaderCompiler; + + funcs->releaseShaderCompiler(); +} + +static void qglfResolveRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + typedef void (QGLF_APIENTRYP type_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorage")); +#ifdef QT_OPENGL_ES + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageOES")); + } +#endif + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageEXT")); + } + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageARB")); + } + + if (funcs->renderbufferStorage) + funcs->renderbufferStorage(target, internalformat, width, height); + else + funcs->renderbufferStorage = qglfResolveRenderbufferStorage; +} + +static void qglfResolveSampleCoverage(GLclampf value, GLboolean invert) +{ + typedef void (QGLF_APIENTRYP type_glSampleCoverage)(GLclampf value, GLboolean invert); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverage")); +#ifdef QT_OPENGL_ES + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageOES")); + } +#endif + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageEXT")); + } + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageARB")); + } + + if (funcs->sampleCoverage) + funcs->sampleCoverage(value, invert); + else + funcs->sampleCoverage = qglfResolveSampleCoverage; +} + +static void qglfResolveShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ + typedef void (QGLF_APIENTRYP type_glShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinary")); + if (!funcs->shaderBinary) { + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinaryARB")); + } + + if (funcs->shaderBinary) + funcs->shaderBinary(n, shaders, binaryformat, binary, length); + else + funcs->shaderBinary = qglfResolveShaderBinary; +} + +static void qglfResolveShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ + typedef void (QGLF_APIENTRYP type_glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSource")); + if (!funcs->shaderSource) { + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSourceARB")); + } + + if (funcs->shaderSource) + funcs->shaderSource(shader, count, string, length); + else + funcs->shaderSource = qglfResolveShaderSource; +} + +static void qglfResolveStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateOES")); + } +#endif + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateEXT")); + } + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateARB")); + } + + if (funcs->stencilFuncSeparate) + funcs->stencilFuncSeparate(face, func, ref, mask); + else + funcs->stencilFuncSeparate = qglfResolveStencilFuncSeparate; +} + +static void qglfResolveStencilMaskSeparate(GLenum face, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilMaskSeparate)(GLenum face, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateOES")); + } +#endif + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateEXT")); + } + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateARB")); + } + + if (funcs->stencilMaskSeparate) + funcs->stencilMaskSeparate(face, mask); + else + funcs->stencilMaskSeparate = qglfResolveStencilMaskSeparate; +} + +static void qglfResolveStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + typedef void (QGLF_APIENTRYP type_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateOES")); + } +#endif + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateEXT")); + } + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateARB")); + } + + if (funcs->stencilOpSeparate) + funcs->stencilOpSeparate(face, fail, zfail, zpass); + else + funcs->stencilOpSeparate = qglfResolveStencilOpSeparate; +} + +static void qglfResolveUniform1f(GLint location, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1f)(GLint location, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1f")); + if (!funcs->uniform1f) { + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1fARB")); + } + + if (funcs->uniform1f) + funcs->uniform1f(location, x); + else + funcs->uniform1f = qglfResolveUniform1f; +} + +static void qglfResolveUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fv")); + if (!funcs->uniform1fv) { + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fvARB")); + } + + if (funcs->uniform1fv) + funcs->uniform1fv(location, count, v); + else + funcs->uniform1fv = qglfResolveUniform1fv; +} + +static void qglfResolveUniform1i(GLint location, GLint x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1i)(GLint location, GLint x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1i")); + if (!funcs->uniform1i) { + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1iARB")); + } + + if (funcs->uniform1i) + funcs->uniform1i(location, x); + else + funcs->uniform1i = qglfResolveUniform1i; +} + +static void qglfResolveUniform1iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1iv")); + if (!funcs->uniform1iv) { + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1ivARB")); + } + + if (funcs->uniform1iv) + funcs->uniform1iv(location, count, v); + else + funcs->uniform1iv = qglfResolveUniform1iv; +} + +static void qglfResolveUniform2f(GLint location, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2f)(GLint location, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2f")); + if (!funcs->uniform2f) { + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2fARB")); + } + + if (funcs->uniform2f) + funcs->uniform2f(location, x, y); + else + funcs->uniform2f = qglfResolveUniform2f; +} + +static void qglfResolveUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fv")); + if (!funcs->uniform2fv) { + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fvARB")); + } + + if (funcs->uniform2fv) + funcs->uniform2fv(location, count, v); + else + funcs->uniform2fv = qglfResolveUniform2fv; +} + +static void qglfResolveUniform2i(GLint location, GLint x, GLint y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2i)(GLint location, GLint x, GLint y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2i")); + if (!funcs->uniform2i) { + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2iARB")); + } + + if (funcs->uniform2i) + funcs->uniform2i(location, x, y); + else + funcs->uniform2i = qglfResolveUniform2i; +} + +static void qglfResolveUniform2iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2iv")); + if (!funcs->uniform2iv) { + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2ivARB")); + } + + if (funcs->uniform2iv) + funcs->uniform2iv(location, count, v); + else + funcs->uniform2iv = qglfResolveUniform2iv; +} + +static void qglfResolveUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3f")); + if (!funcs->uniform3f) { + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3fARB")); + } + + if (funcs->uniform3f) + funcs->uniform3f(location, x, y, z); + else + funcs->uniform3f = qglfResolveUniform3f; +} + +static void qglfResolveUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fv")); + if (!funcs->uniform3fv) { + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fvARB")); + } + + if (funcs->uniform3fv) + funcs->uniform3fv(location, count, v); + else + funcs->uniform3fv = qglfResolveUniform3fv; +} + +static void qglfResolveUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3i)(GLint location, GLint x, GLint y, GLint z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3i")); + if (!funcs->uniform3i) { + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3iARB")); + } + + if (funcs->uniform3i) + funcs->uniform3i(location, x, y, z); + else + funcs->uniform3i = qglfResolveUniform3i; +} + +static void qglfResolveUniform3iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3iv")); + if (!funcs->uniform3iv) { + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3ivARB")); + } + + if (funcs->uniform3iv) + funcs->uniform3iv(location, count, v); + else + funcs->uniform3iv = qglfResolveUniform3iv; +} + +static void qglfResolveUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4f")); + if (!funcs->uniform4f) { + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4fARB")); + } + + if (funcs->uniform4f) + funcs->uniform4f(location, x, y, z, w); + else + funcs->uniform4f = qglfResolveUniform4f; +} + +static void qglfResolveUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fv")); + if (!funcs->uniform4fv) { + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fvARB")); + } + + if (funcs->uniform4fv) + funcs->uniform4fv(location, count, v); + else + funcs->uniform4fv = qglfResolveUniform4fv; +} + +static void qglfResolveUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4i")); + if (!funcs->uniform4i) { + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4iARB")); + } + + if (funcs->uniform4i) + funcs->uniform4i(location, x, y, z, w); + else + funcs->uniform4i = qglfResolveUniform4i; +} + +static void qglfResolveUniform4iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4iv")); + if (!funcs->uniform4iv) { + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4ivARB")); + } + + if (funcs->uniform4iv) + funcs->uniform4iv(location, count, v); + else + funcs->uniform4iv = qglfResolveUniform4iv; +} + +static void qglfResolveUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fv")); + if (!funcs->uniformMatrix2fv) { + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fvARB")); + } + + if (funcs->uniformMatrix2fv) + funcs->uniformMatrix2fv(location, count, transpose, value); + else + funcs->uniformMatrix2fv = qglfResolveUniformMatrix2fv; +} + +static void qglfResolveUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fv")); + if (!funcs->uniformMatrix3fv) { + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fvARB")); + } + + if (funcs->uniformMatrix3fv) + funcs->uniformMatrix3fv(location, count, transpose, value); + else + funcs->uniformMatrix3fv = qglfResolveUniformMatrix3fv; +} + +static void qglfResolveUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fv")); + if (!funcs->uniformMatrix4fv) { + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fvARB")); + } + + if (funcs->uniformMatrix4fv) + funcs->uniformMatrix4fv(location, count, transpose, value); + else + funcs->uniformMatrix4fv = qglfResolveUniformMatrix4fv; +} + +static void qglfResolveUseProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glUseProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgram")); + if (!funcs->useProgram) { + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgramObjectARB")); + } + + if (funcs->useProgram) + funcs->useProgram(program); + else + funcs->useProgram = qglfResolveUseProgram; +} + +static void qglfResolveValidateProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glValidateProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgram")); + if (!funcs->validateProgram) { + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgramARB")); + } + + if (funcs->validateProgram) + funcs->validateProgram(program); + else + funcs->validateProgram = qglfResolveValidateProgram; +} + +static void qglfResolveVertexAttrib1f(GLuint indx, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1f)(GLuint indx, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1f")); + if (!funcs->vertexAttrib1f) { + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1fARB")); + } + + if (funcs->vertexAttrib1f) + funcs->vertexAttrib1f(indx, x); + else + funcs->vertexAttrib1f = qglfResolveVertexAttrib1f; +} + +static void qglfResolveVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fv")); + if (!funcs->vertexAttrib1fv) { + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fvARB")); + } + + if (funcs->vertexAttrib1fv) + funcs->vertexAttrib1fv(indx, values); + else + funcs->vertexAttrib1fv = qglfResolveVertexAttrib1fv; +} + +static void qglfResolveVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2f")); + if (!funcs->vertexAttrib2f) { + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2fARB")); + } + + if (funcs->vertexAttrib2f) + funcs->vertexAttrib2f(indx, x, y); + else + funcs->vertexAttrib2f = qglfResolveVertexAttrib2f; +} + +static void qglfResolveVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fv")); + if (!funcs->vertexAttrib2fv) { + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fvARB")); + } + + if (funcs->vertexAttrib2fv) + funcs->vertexAttrib2fv(indx, values); + else + funcs->vertexAttrib2fv = qglfResolveVertexAttrib2fv; +} + +static void qglfResolveVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3f")); + if (!funcs->vertexAttrib3f) { + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3fARB")); + } + + if (funcs->vertexAttrib3f) + funcs->vertexAttrib3f(indx, x, y, z); + else + funcs->vertexAttrib3f = qglfResolveVertexAttrib3f; +} + +static void qglfResolveVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fv")); + if (!funcs->vertexAttrib3fv) { + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fvARB")); + } + + if (funcs->vertexAttrib3fv) + funcs->vertexAttrib3fv(indx, values); + else + funcs->vertexAttrib3fv = qglfResolveVertexAttrib3fv; +} + +static void qglfResolveVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4f")); + if (!funcs->vertexAttrib4f) { + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4fARB")); + } + + if (funcs->vertexAttrib4f) + funcs->vertexAttrib4f(indx, x, y, z, w); + else + funcs->vertexAttrib4f = qglfResolveVertexAttrib4f; +} + +static void qglfResolveVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fv")); + if (!funcs->vertexAttrib4fv) { + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fvARB")); + } + + if (funcs->vertexAttrib4fv) + funcs->vertexAttrib4fv(indx, values); + else + funcs->vertexAttrib4fv = qglfResolveVertexAttrib4fv; +} + +static void qglfResolveVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointer")); + if (!funcs->vertexAttribPointer) { + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointerARB")); + } + + if (funcs->vertexAttribPointer) + funcs->vertexAttribPointer(indx, size, type, normalized, stride, ptr); + else + funcs->vertexAttribPointer = qglfResolveVertexAttribPointer; +} + +#endif // !QT_OPENGL_ES_2 + +QGLFunctionsPrivate::QGLFunctionsPrivate(const QGLContext *) +{ +#ifndef QT_OPENGL_ES_2 + activeTexture = qglfResolveActiveTexture; + attachShader = qglfResolveAttachShader; + bindAttribLocation = qglfResolveBindAttribLocation; + bindBuffer = qglfResolveBindBuffer; + bindFramebuffer = qglfResolveBindFramebuffer; + bindRenderbuffer = qglfResolveBindRenderbuffer; + blendColor = qglfResolveBlendColor; + blendEquation = qglfResolveBlendEquation; + blendEquationSeparate = qglfResolveBlendEquationSeparate; + blendFuncSeparate = qglfResolveBlendFuncSeparate; + bufferData = qglfResolveBufferData; + bufferSubData = qglfResolveBufferSubData; + checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + compileShader = qglfResolveCompileShader; + compressedTexImage2D = qglfResolveCompressedTexImage2D; + compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; + createProgram = qglfResolveCreateProgram; + createShader = qglfResolveCreateShader; + deleteBuffers = qglfResolveDeleteBuffers; + deleteFramebuffers = qglfResolveDeleteFramebuffers; + deleteProgram = qglfResolveDeleteProgram; + deleteRenderbuffers = qglfResolveDeleteRenderbuffers; + deleteShader = qglfResolveDeleteShader; + detachShader = qglfResolveDetachShader; + disableVertexAttribArray = qglfResolveDisableVertexAttribArray; + enableVertexAttribArray = qglfResolveEnableVertexAttribArray; + framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; + framebufferTexture2D = qglfResolveFramebufferTexture2D; + genBuffers = qglfResolveGenBuffers; + generateMipmap = qglfResolveGenerateMipmap; + genFramebuffers = qglfResolveGenFramebuffers; + genRenderbuffers = qglfResolveGenRenderbuffers; + getActiveAttrib = qglfResolveGetActiveAttrib; + getActiveUniform = qglfResolveGetActiveUniform; + getAttachedShaders = qglfResolveGetAttachedShaders; + getAttribLocation = qglfResolveGetAttribLocation; + getBufferParameteriv = qglfResolveGetBufferParameteriv; + getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; + getProgramiv = qglfResolveGetProgramiv; + getProgramInfoLog = qglfResolveGetProgramInfoLog; + getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; + getShaderiv = qglfResolveGetShaderiv; + getShaderInfoLog = qglfResolveGetShaderInfoLog; + getShaderPrecisionFormat = qglfResolveGetShaderPrecisionFormat; + getShaderSource = qglfResolveGetShaderSource; + getUniformfv = qglfResolveGetUniformfv; + getUniformiv = qglfResolveGetUniformiv; + getUniformLocation = qglfResolveGetUniformLocation; + getVertexAttribfv = qglfResolveGetVertexAttribfv; + getVertexAttribiv = qglfResolveGetVertexAttribiv; + getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; + isBuffer = qglfResolveIsBuffer; + isFramebuffer = qglfResolveIsFramebuffer; + isProgram = qglfResolveIsProgram; + isRenderbuffer = qglfResolveIsRenderbuffer; + isShader = qglfResolveIsShader; + linkProgram = qglfResolveLinkProgram; + releaseShaderCompiler = qglfResolveReleaseShaderCompiler; + renderbufferStorage = qglfResolveRenderbufferStorage; + sampleCoverage = qglfResolveSampleCoverage; + shaderBinary = qglfResolveShaderBinary; + shaderSource = qglfResolveShaderSource; + stencilFuncSeparate = qglfResolveStencilFuncSeparate; + stencilMaskSeparate = qglfResolveStencilMaskSeparate; + stencilOpSeparate = qglfResolveStencilOpSeparate; + uniform1f = qglfResolveUniform1f; + uniform1fv = qglfResolveUniform1fv; + uniform1i = qglfResolveUniform1i; + uniform1iv = qglfResolveUniform1iv; + uniform2f = qglfResolveUniform2f; + uniform2fv = qglfResolveUniform2fv; + uniform2i = qglfResolveUniform2i; + uniform2iv = qglfResolveUniform2iv; + uniform3f = qglfResolveUniform3f; + uniform3fv = qglfResolveUniform3fv; + uniform3i = qglfResolveUniform3i; + uniform3iv = qglfResolveUniform3iv; + uniform4f = qglfResolveUniform4f; + uniform4fv = qglfResolveUniform4fv; + uniform4i = qglfResolveUniform4i; + uniform4iv = qglfResolveUniform4iv; + uniformMatrix2fv = qglfResolveUniformMatrix2fv; + uniformMatrix3fv = qglfResolveUniformMatrix3fv; + uniformMatrix4fv = qglfResolveUniformMatrix4fv; + useProgram = qglfResolveUseProgram; + validateProgram = qglfResolveValidateProgram; + vertexAttrib1f = qglfResolveVertexAttrib1f; + vertexAttrib1fv = qglfResolveVertexAttrib1fv; + vertexAttrib2f = qglfResolveVertexAttrib2f; + vertexAttrib2fv = qglfResolveVertexAttrib2fv; + vertexAttrib3f = qglfResolveVertexAttrib3f; + vertexAttrib3fv = qglfResolveVertexAttrib3fv; + vertexAttrib4f = qglfResolveVertexAttrib4f; + vertexAttrib4fv = qglfResolveVertexAttrib4fv; + vertexAttribPointer = qglfResolveVertexAttribPointer; +#endif // !QT_OPENGL_ES_2 +} + +QT_END_NAMESPACE diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h new file mode 100644 index 0000000..e06de7f --- /dev/null +++ b/src/opengl/qglfunctions.h @@ -0,0 +1,2290 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLFUNCTIONS_H +#define QGLFUNCTIONS_H + +#include <QtOpenGL/qgl.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenGL) + +// Types that aren't defined in all system's gl.h files. +typedef ptrdiff_t qgl_GLintptr; +typedef ptrdiff_t qgl_GLsizeiptr; + +#ifndef Q_WS_MAC +# ifndef QGLF_APIENTRYP +# ifdef QGLF_APIENTRY +# define QGLF_APIENTRYP QGLF_APIENTRY * +# else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +# endif +# endif +#else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +#endif + +struct QGLFunctionsPrivate; + +// Undefine any macros from GLEW, qglextensions_p.h, etc that +// may interfere with the definition of QGLFunctions. +#undef glActiveTexture +#undef glAttachShader +#undef glBindAttribLocation +#undef glBindBuffer +#undef glBindFramebuffer +#undef glBindRenderbuffer +#undef glBlendColor +#undef glBlendEquation +#undef glBlendEquationSeparate +#undef glBlendFuncSeparate +#undef glBufferData +#undef glBufferSubData +#undef glCheckFramebufferStatus +#undef glClearDepthf +#undef glCompileShader +#undef glCompressedTexImage2D +#undef glCompressedTexSubImage2D +#undef glCreateProgram +#undef glCreateShader +#undef glDeleteBuffers +#undef glDeleteFramebuffers +#undef glDeleteProgram +#undef glDeleteRenderbuffers +#undef glDeleteShader +#undef glDepthRangef +#undef glDetachShader +#undef glDisableVertexAttribArray +#undef glEnableVertexAttribArray +#undef glFramebufferRenderbuffer +#undef glFramebufferTexture2D +#undef glGenBuffers +#undef glGenerateMipmap +#undef glGenFramebuffers +#undef glGenRenderbuffers +#undef glGetActiveAttrib +#undef glGetActiveUniform +#undef glGetAttachedShaders +#undef glGetAttribLocation +#undef glGetBufferParameteriv +#undef glGetFramebufferAttachmentParameteriv +#undef glGetProgramiv +#undef glGetProgramInfoLog +#undef glGetRenderbufferParameteriv +#undef glGetShaderiv +#undef glGetShaderInfoLog +#undef glGetShaderPrecisionFormat +#undef glGetShaderSource +#undef glGetUniformfv +#undef glGetUniformiv +#undef glGetUniformLocation +#undef glGetVertexAttribfv +#undef glGetVertexAttribiv +#undef glGetVertexAttribPointerv +#undef glIsBuffer +#undef glIsFramebuffer +#undef glIsProgram +#undef glIsRenderbuffer +#undef glIsShader +#undef glLinkProgram +#undef glReleaseShaderCompiler +#undef glRenderbufferStorage +#undef glSampleCoverage +#undef glShaderBinary +#undef glShaderSource +#undef glStencilFuncSeparate +#undef glStencilMaskSeparate +#undef glStencilOpSeparate +#undef glUniform1f +#undef glUniform1fv +#undef glUniform1i +#undef glUniform1iv +#undef glUniform2f +#undef glUniform2fv +#undef glUniform2i +#undef glUniform2iv +#undef glUniform3f +#undef glUniform3fv +#undef glUniform3i +#undef glUniform3iv +#undef glUniform4f +#undef glUniform4fv +#undef glUniform4i +#undef glUniform4iv +#undef glUniformMatrix2fv +#undef glUniformMatrix3fv +#undef glUniformMatrix4fv +#undef glUseProgram +#undef glValidateProgram +#undef glVertexAttrib1f +#undef glVertexAttrib1fv +#undef glVertexAttrib2f +#undef glVertexAttrib2fv +#undef glVertexAttrib3f +#undef glVertexAttrib3fv +#undef glVertexAttrib4f +#undef glVertexAttrib4fv +#undef glVertexAttribPointer + +class Q_OPENGL_EXPORT QGLFunctions +{ +public: + QGLFunctions(); + explicit QGLFunctions(const QGLContext *context); + ~QGLFunctions() {} + + enum OpenGLFeature + { + Multitexture = 0x0001, + Shaders = 0x0002, + Buffers = 0x0004, + Framebuffers = 0x0008, + BlendColor = 0x0010, + BlendEquation = 0x0020, + BlendEquationSeparate = 0x0040, + BlendFuncSeparate = 0x0080, + BlendSubtract = 0x0100, + CompressedTextures = 0x0200, + Multisample = 0x0400, + StencilSeparate = 0x0800, + NPOTTextures = 0x1000 + }; + Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature) + + QGLFunctions::OpenGLFeatures openGLFeatures() const; + bool hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const; + + void initializeGLFunctions(const QGLContext *context = 0); + + void glActiveTexture(GLenum texture); + void glAttachShader(GLuint program, GLuint shader); + void glBindAttribLocation(GLuint program, GLuint index, const char* name); + void glBindBuffer(GLenum target, GLuint buffer); + void glBindFramebuffer(GLenum target, GLuint framebuffer); + void glBindRenderbuffer(GLenum target, GLuint renderbuffer); + void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void glBlendEquation(GLenum mode); + void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum glCheckFramebufferStatus(GLenum target); + void glClearDepthf(GLclampf depth); + void glCompileShader(GLuint shader); + void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint glCreateProgram(); + GLuint glCreateShader(GLenum type); + void glDeleteBuffers(GLsizei n, const GLuint* buffers); + void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers); + void glDeleteProgram(GLuint program); + void glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); + void glDeleteShader(GLuint shader); + void glDepthRangef(GLclampf zNear, GLclampf zFar); + void glDetachShader(GLuint program, GLuint shader); + void glDisableVertexAttribArray(GLuint index); + void glEnableVertexAttribArray(GLuint index); + void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void glGenBuffers(GLsizei n, GLuint* buffers); + void glGenerateMipmap(GLenum target); + void glGenFramebuffers(GLsizei n, GLuint* framebuffers); + void glGenRenderbuffers(GLsizei n, GLuint* renderbuffers); + void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int glGetAttribLocation(GLuint program, const char* name); + void glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void glGetProgramiv(GLuint program, GLenum pname, GLint* params); + void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetShaderiv(GLuint shader, GLenum pname, GLint* params); + void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void glGetUniformfv(GLuint program, GLint location, GLfloat* params); + void glGetUniformiv(GLuint program, GLint location, GLint* params); + int glGetUniformLocation(GLuint program, const char* name); + void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); + void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params); + void glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer); + GLboolean glIsBuffer(GLuint buffer); + GLboolean glIsFramebuffer(GLuint framebuffer); + GLboolean glIsProgram(GLuint program); + GLboolean glIsRenderbuffer(GLuint renderbuffer); + GLboolean glIsShader(GLuint shader); + void glLinkProgram(GLuint program); + void glReleaseShaderCompiler(); + void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void glSampleCoverage(GLclampf value, GLboolean invert); + void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length); + void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void glStencilMaskSeparate(GLenum face, GLuint mask); + void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void glUniform1f(GLint location, GLfloat x); + void glUniform1fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform1i(GLint location, GLint x); + void glUniform1iv(GLint location, GLsizei count, const GLint* v); + void glUniform2f(GLint location, GLfloat x, GLfloat y); + void glUniform2fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform2i(GLint location, GLint x, GLint y); + void glUniform2iv(GLint location, GLsizei count, const GLint* v); + void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z); + void glUniform3fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform3i(GLint location, GLint x, GLint y, GLint z); + void glUniform3iv(GLint location, GLsizei count, const GLint* v); + void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glUniform4fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w); + void glUniform4iv(GLint location, GLsizei count, const GLint* v); + void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUseProgram(GLuint program); + void glValidateProgram(GLuint program); + void glVertexAttrib1f(GLuint indx, GLfloat x); + void glVertexAttrib1fv(GLuint indx, const GLfloat* values); + void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + void glVertexAttrib2fv(GLuint indx, const GLfloat* values); + void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void glVertexAttrib3fv(GLuint indx, const GLfloat* values); + void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glVertexAttrib4fv(GLuint indx, const GLfloat* values); + void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + +private: + QGLFunctionsPrivate *d_ptr; + static bool isInitialized(const QGLFunctionsPrivate *d) { return d != 0; } +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFunctions::OpenGLFeatures) + +struct QGLFunctionsPrivate +{ + QGLFunctionsPrivate(const QGLContext *context = 0); + +#ifndef QT_OPENGL_ES_2 + void (QGLF_APIENTRYP activeTexture)(GLenum texture); + void (QGLF_APIENTRYP attachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP bindAttribLocation)(GLuint program, GLuint index, const char* name); + void (QGLF_APIENTRYP bindBuffer)(GLenum target, GLuint buffer); + void (QGLF_APIENTRYP bindFramebuffer)(GLenum target, GLuint framebuffer); + void (QGLF_APIENTRYP bindRenderbuffer)(GLenum target, GLuint renderbuffer); + void (QGLF_APIENTRYP blendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (QGLF_APIENTRYP blendEquation)(GLenum mode); + void (QGLF_APIENTRYP blendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + void (QGLF_APIENTRYP blendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void (QGLF_APIENTRYP bufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void (QGLF_APIENTRYP bufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum (QGLF_APIENTRYP checkFramebufferStatus)(GLenum target); + void (QGLF_APIENTRYP compileShader)(GLuint shader); + void (QGLF_APIENTRYP compressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void (QGLF_APIENTRYP compressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint (QGLF_APIENTRYP createProgram)(); + GLuint (QGLF_APIENTRYP createShader)(GLenum type); + void (QGLF_APIENTRYP deleteBuffers)(GLsizei n, const GLuint* buffers); + void (QGLF_APIENTRYP deleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + void (QGLF_APIENTRYP deleteProgram)(GLuint program); + void (QGLF_APIENTRYP deleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + void (QGLF_APIENTRYP deleteShader)(GLuint shader); + void (QGLF_APIENTRYP detachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP disableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP enableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP framebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void (QGLF_APIENTRYP framebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void (QGLF_APIENTRYP genBuffers)(GLsizei n, GLuint* buffers); + void (QGLF_APIENTRYP generateMipmap)(GLenum target); + void (QGLF_APIENTRYP genFramebuffers)(GLsizei n, GLuint* framebuffers); + void (QGLF_APIENTRYP genRenderbuffers)(GLsizei n, GLuint* renderbuffers); + void (QGLF_APIENTRYP getActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int (QGLF_APIENTRYP getAttribLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramiv)(GLuint program, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderiv)(GLuint shader, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void (QGLF_APIENTRYP getShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void (QGLF_APIENTRYP getUniformfv)(GLuint program, GLint location, GLfloat* params); + void (QGLF_APIENTRYP getUniformiv)(GLuint program, GLint location, GLint* params); + int (QGLF_APIENTRYP getUniformLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + void (QGLF_APIENTRYP getVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + GLboolean (QGLF_APIENTRYP isBuffer)(GLuint buffer); + GLboolean (QGLF_APIENTRYP isFramebuffer)(GLuint framebuffer); + GLboolean (QGLF_APIENTRYP isProgram)(GLuint program); + GLboolean (QGLF_APIENTRYP isRenderbuffer)(GLuint renderbuffer); + GLboolean (QGLF_APIENTRYP isShader)(GLuint shader); + void (QGLF_APIENTRYP linkProgram)(GLuint program); + void (QGLF_APIENTRYP releaseShaderCompiler)(); + void (QGLF_APIENTRYP renderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void (QGLF_APIENTRYP sampleCoverage)(GLclampf value, GLboolean invert); + void (QGLF_APIENTRYP shaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void (QGLF_APIENTRYP shaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + void (QGLF_APIENTRYP stencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + void (QGLF_APIENTRYP stencilMaskSeparate)(GLenum face, GLuint mask); + void (QGLF_APIENTRYP stencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void (QGLF_APIENTRYP uniform1f)(GLint location, GLfloat x); + void (QGLF_APIENTRYP uniform1fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform1i)(GLint location, GLint x); + void (QGLF_APIENTRYP uniform1iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform2f)(GLint location, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP uniform2fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform2i)(GLint location, GLint x, GLint y); + void (QGLF_APIENTRYP uniform2iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP uniform3fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform3i)(GLint location, GLint x, GLint y, GLint z); + void (QGLF_APIENTRYP uniform3iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP uniform4fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + void (QGLF_APIENTRYP uniform4iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP useProgram)(GLuint program); + void (QGLF_APIENTRYP validateProgram)(GLuint program); + void (QGLF_APIENTRYP vertexAttrib1f)(GLuint indx, GLfloat x); + void (QGLF_APIENTRYP vertexAttrib1fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP vertexAttrib2fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP vertexAttrib3fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP vertexAttrib4fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); +#endif +}; + +inline void QGLFunctions::glActiveTexture(GLenum texture) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glActiveTexture(texture); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->activeTexture(texture); +#endif +} + +inline void QGLFunctions::glAttachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glAttachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->attachShader(program, shader); +#endif +} + +inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindAttribLocation(program, index, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindAttribLocation(program, index, name); +#endif +} + +inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBindBuffer(target, buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindBuffer(target, buffer); +#endif +} + +inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindFramebuffer(target, framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindFramebuffer(target, framebuffer); +#endif +} + +inline void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindRenderbuffer(target, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindRenderbuffer(target, renderbuffer); +#endif +} + +inline void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendColor(red, green, blue, alpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendColor(red, green, blue, alpha); +#endif +} + +inline void QGLFunctions::glBlendEquation(GLenum mode) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquation(mode); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquation(mode); +#endif +} + +inline void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquationSeparate(modeRGB, modeAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquationSeparate(modeRGB, modeAlpha); +#endif +} + +inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#endif +} + +inline void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferData(target, size, data, usage); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferData(target, size, data, usage); +#endif +} + +inline void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferSubData(target, offset, size, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferSubData(target, offset, size, data); +#endif +} + +inline GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCheckFramebufferStatus(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->checkFramebufferStatus(target); +#endif +} + +inline void QGLFunctions::glClearDepthf(GLclampf depth) +{ +#ifndef QT_OPENGL_ES + ::glClearDepth(depth); +#else + ::glClearDepthf(depth); +#endif +} + +inline void QGLFunctions::glCompileShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glCompileShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compileShader(shader); +#endif +} + +inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#endif +} + +inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#endif +} + +inline GLuint QGLFunctions::glCreateProgram() +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateProgram(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createProgram(); +#endif +} + +inline GLuint QGLFunctions::glCreateShader(GLenum type) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateShader(type); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createShader(type); +#endif +} + +inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glDeleteBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glDeleteProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteProgram(program); +#endif +} + +inline void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glDeleteShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteShader(shader); +#endif +} + +inline void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) +{ +#ifndef QT_OPENGL_ES + ::glDepthRange(zNear, zFar); +#else + ::glDepthRangef(zNear, zFar); +#endif +} + +inline void QGLFunctions::glDetachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDetachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->detachShader(program, shader); +#endif +} + +inline void QGLFunctions::glDisableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glDisableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->disableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glEnableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glEnableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->enableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#endif +} + +inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferTexture2D(target, attachment, textarget, texture, level); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferTexture2D(target, attachment, textarget, texture, level); +#endif +} + +inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glGenBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glGenerateMipmap(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenerateMipmap(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->generateMipmap(target); +#endif +} + +inline void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveAttrib(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveAttrib(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveUniform(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveUniform(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetAttachedShaders(program, maxcount, count, shaders); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getAttachedShaders(program, maxcount, count, shaders); +#endif +} + +inline int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetAttribLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getAttribLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetBufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getBufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getFramebufferAttachmentParameteriv(target, attachment, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramiv(program, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramiv(program, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramInfoLog(program, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramInfoLog(program, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetRenderbufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getRenderbufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderiv(shader, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderiv(shader, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderInfoLog(shader, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderInfoLog(shader, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#endif +} + +inline void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderSource(shader, bufsize, length, source); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderSource(shader, bufsize, length, source); +#endif +} + +inline void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformfv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformfv(program, location, params); +#endif +} + +inline void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformiv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformiv(program, location, params); +#endif +} + +inline int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetUniformLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getUniformLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribfv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribfv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribiv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribiv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribPointerv(index, pname, pointer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribPointerv(index, pname, pointer); +#endif +} + +inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + return ::glIsBuffer(buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isBuffer(buffer); +#endif +} + +inline GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsFramebuffer(framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isFramebuffer(framebuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isProgram(program); +#endif +} + +inline GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsRenderbuffer(renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isRenderbuffer(renderbuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isShader(shader); +#endif +} + +inline void QGLFunctions::glLinkProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glLinkProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->linkProgram(program); +#endif +} + +inline void QGLFunctions::glReleaseShaderCompiler() +{ +#if defined(QT_OPENGL_ES_2) + ::glReleaseShaderCompiler(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->releaseShaderCompiler(); +#endif +} + +inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ +#if defined(QT_OPENGL_ES_2) + ::glRenderbufferStorage(target, internalformat, width, height); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->renderbufferStorage(target, internalformat, width, height); +#endif +} + +inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glSampleCoverage(value, invert); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->sampleCoverage(value, invert); +#endif +} + +inline void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderBinary(n, shaders, binaryformat, binary, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderBinary(n, shaders, binaryformat, binary, length); +#endif +} + +inline void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderSource(shader, count, string, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderSource(shader, count, string, length); +#endif +} + +inline void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilFuncSeparate(face, func, ref, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilFuncSeparate(face, func, ref, mask); +#endif +} + +inline void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilMaskSeparate(face, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilMaskSeparate(face, mask); +#endif +} + +inline void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilOpSeparate(face, fail, zfail, zpass); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilOpSeparate(face, fail, zfail, zpass); +#endif +} + +inline void QGLFunctions::glUniform1f(GLint location, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1f(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1f(location, x); +#endif +} + +inline void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform1i(GLint location, GLint x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1i(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1i(location, x); +#endif +} + +inline void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2f(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2f(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2i(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2i(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3f(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3f(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3i(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3i(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4f(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4f(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4i(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4i(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix2fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix2fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix3fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix3fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix4fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix4fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUseProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glUseProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->useProgram(program); +#endif +} + +inline void QGLFunctions::glValidateProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glValidateProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->validateProgram(program); +#endif +} + +inline void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1f(indx, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1f(indx, x); +#endif +} + +inline void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2f(indx, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2f(indx, x, y); +#endif +} + +inline void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3f(indx, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3f(indx, x, y, z); +#endif +} + +inline void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4f(indx, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4f(indx, x, y, z, w); +#endif +} + +inline void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttribPointer(indx, size, type, normalized, stride, ptr); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttribPointer(indx, size, type, normalized, stride, ptr); +#endif +} + +#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#endif +#ifndef GL_ACTIVE_ATTRIBUTES +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#endif +#ifndef GL_ACTIVE_TEXTURE +#define GL_ACTIVE_TEXTURE 0x84E0 +#endif +#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#endif +#ifndef GL_ACTIVE_UNIFORMS +#define GL_ACTIVE_UNIFORMS 0x8B86 +#endif +#ifndef GL_ALIASED_LINE_WIDTH_RANGE +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif +#ifndef GL_ALIASED_POINT_SIZE_RANGE +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#endif +#ifndef GL_ALPHA +#define GL_ALPHA 0x1906 +#endif +#ifndef GL_ALPHA_BITS +#define GL_ALPHA_BITS 0x0D55 +#endif +#ifndef GL_ALWAYS +#define GL_ALWAYS 0x0207 +#endif +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_ARRAY_BUFFER_BINDING +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#endif +#ifndef GL_ATTACHED_SHADERS +#define GL_ATTACHED_SHADERS 0x8B85 +#endif +#ifndef GL_BACK +#define GL_BACK 0x0405 +#endif +#ifndef GL_BLEND +#define GL_BLEND 0x0BE2 +#endif +#ifndef GL_BLEND_COLOR +#define GL_BLEND_COLOR 0x8005 +#endif +#ifndef GL_BLEND_DST_ALPHA +#define GL_BLEND_DST_ALPHA 0x80CA +#endif +#ifndef GL_BLEND_DST_RGB +#define GL_BLEND_DST_RGB 0x80C8 +#endif +#ifndef GL_BLEND_EQUATION +#define GL_BLEND_EQUATION 0x8009 +#endif +#ifndef GL_BLEND_EQUATION_ALPHA +#define GL_BLEND_EQUATION_ALPHA 0x883D +#endif +#ifndef GL_BLEND_EQUATION_RGB +#define GL_BLEND_EQUATION_RGB 0x8009 +#endif +#ifndef GL_BLEND_SRC_ALPHA +#define GL_BLEND_SRC_ALPHA 0x80CB +#endif +#ifndef GL_BLEND_SRC_RGB +#define GL_BLEND_SRC_RGB 0x80C9 +#endif +#ifndef GL_BLUE_BITS +#define GL_BLUE_BITS 0x0D54 +#endif +#ifndef GL_BOOL +#define GL_BOOL 0x8B56 +#endif +#ifndef GL_BOOL_VEC2 +#define GL_BOOL_VEC2 0x8B57 +#endif +#ifndef GL_BOOL_VEC3 +#define GL_BOOL_VEC3 0x8B58 +#endif +#ifndef GL_BOOL_VEC4 +#define GL_BOOL_VEC4 0x8B59 +#endif +#ifndef GL_BUFFER_SIZE +#define GL_BUFFER_SIZE 0x8764 +#endif +#ifndef GL_BUFFER_USAGE +#define GL_BUFFER_USAGE 0x8765 +#endif +#ifndef GL_BYTE +#define GL_BYTE 0x1400 +#endif +#ifndef GL_CCW +#define GL_CCW 0x0901 +#endif +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#endif +#ifndef GL_COLOR_BUFFER_BIT +#define GL_COLOR_BUFFER_BIT 0x00004000 +#endif +#ifndef GL_COLOR_CLEAR_VALUE +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#endif +#ifndef GL_COLOR_WRITEMASK +#define GL_COLOR_WRITEMASK 0x0C23 +#endif +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif +#ifndef GL_COMPRESSED_TEXTURE_FORMATS +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#endif +#ifndef GL_CONSTANT_ALPHA +#define GL_CONSTANT_ALPHA 0x8003 +#endif +#ifndef GL_CONSTANT_COLOR +#define GL_CONSTANT_COLOR 0x8001 +#endif +#ifndef GL_CULL_FACE +#define GL_CULL_FACE 0x0B44 +#endif +#ifndef GL_CULL_FACE_MODE +#define GL_CULL_FACE_MODE 0x0B45 +#endif +#ifndef GL_CURRENT_PROGRAM +#define GL_CURRENT_PROGRAM 0x8B8D +#endif +#ifndef GL_CURRENT_VERTEX_ATTRIB +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#endif +#ifndef GL_CW +#define GL_CW 0x0900 +#endif +#ifndef GL_DECR +#define GL_DECR 0x1E03 +#endif +#ifndef GL_DECR_WRAP +#define GL_DECR_WRAP 0x8508 +#endif +#ifndef GL_DELETE_STATUS +#define GL_DELETE_STATUS 0x8B80 +#endif +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT 0x8D00 +#endif +#ifndef GL_DEPTH_BITS +#define GL_DEPTH_BITS 0x0D56 +#endif +#ifndef GL_DEPTH_BUFFER_BIT +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#endif +#ifndef GL_DEPTH_CLEAR_VALUE +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#endif +#ifndef GL_DEPTH_COMPONENT +#define GL_DEPTH_COMPONENT 0x1902 +#endif +#ifndef GL_DEPTH_COMPONENT16 +#define GL_DEPTH_COMPONENT16 0x81A5 +#endif +#ifndef GL_DEPTH_FUNC +#define GL_DEPTH_FUNC 0x0B74 +#endif +#ifndef GL_DEPTH_RANGE +#define GL_DEPTH_RANGE 0x0B70 +#endif +#ifndef GL_DEPTH_TEST +#define GL_DEPTH_TEST 0x0B71 +#endif +#ifndef GL_DEPTH_WRITEMASK +#define GL_DEPTH_WRITEMASK 0x0B72 +#endif +#ifndef GL_DITHER +#define GL_DITHER 0x0BD0 +#endif +#ifndef GL_DONT_CARE +#define GL_DONT_CARE 0x1100 +#endif +#ifndef GL_DST_ALPHA +#define GL_DST_ALPHA 0x0304 +#endif +#ifndef GL_DST_COLOR +#define GL_DST_COLOR 0x0306 +#endif +#ifndef GL_DYNAMIC_DRAW +#define GL_DYNAMIC_DRAW 0x88E8 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#endif +#ifndef GL_EQUAL +#define GL_EQUAL 0x0202 +#endif +#ifndef GL_EXTENSIONS +#define GL_EXTENSIONS 0x1F03 +#endif +#ifndef GL_FALSE +#define GL_FALSE 0 +#endif +#ifndef GL_FASTEST +#define GL_FASTEST 0x1101 +#endif +#ifndef GL_FIXED +#define GL_FIXED 0x140C +#endif +#ifndef GL_FLOAT +#define GL_FLOAT 0x1406 +#endif +#ifndef GL_FLOAT_MAT2 +#define GL_FLOAT_MAT2 0x8B5A +#endif +#ifndef GL_FLOAT_MAT3 +#define GL_FLOAT_MAT3 0x8B5B +#endif +#ifndef GL_FLOAT_MAT4 +#define GL_FLOAT_MAT4 0x8B5C +#endif +#ifndef GL_FLOAT_VEC2 +#define GL_FLOAT_VEC2 0x8B50 +#endif +#ifndef GL_FLOAT_VEC3 +#define GL_FLOAT_VEC3 0x8B51 +#endif +#ifndef GL_FLOAT_VEC4 +#define GL_FLOAT_VEC4 0x8B52 +#endif +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER 0x8D40 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#endif +#ifndef GL_FRAMEBUFFER_BINDING +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#endif +#ifndef GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#endif +#ifndef GL_FRAMEBUFFER_UNSUPPORTED +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#endif +#ifndef GL_FRONT +#define GL_FRONT 0x0404 +#endif +#ifndef GL_FRONT_AND_BACK +#define GL_FRONT_AND_BACK 0x0408 +#endif +#ifndef GL_FRONT_FACE +#define GL_FRONT_FACE 0x0B46 +#endif +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif +#ifndef GL_FUNC_REVERSE_SUBTRACT +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#endif +#ifndef GL_FUNC_SUBTRACT +#define GL_FUNC_SUBTRACT 0x800A +#endif +#ifndef GL_GENERATE_MIPMAP_HINT +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#endif +#ifndef GL_GEQUAL +#define GL_GEQUAL 0x0206 +#endif +#ifndef GL_GREATER +#define GL_GREATER 0x0204 +#endif +#ifndef GL_GREEN_BITS +#define GL_GREEN_BITS 0x0D53 +#endif +#ifndef GL_HIGH_FLOAT +#define GL_HIGH_FLOAT 0x8DF2 +#endif +#ifndef GL_HIGH_INT +#define GL_HIGH_INT 0x8DF5 +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_TYPE +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#endif +#ifndef GL_INCR +#define GL_INCR 0x1E02 +#endif +#ifndef GL_INCR_WRAP +#define GL_INCR_WRAP 0x8507 +#endif +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif +#ifndef GL_INT +#define GL_INT 0x1404 +#endif +#ifndef GL_INT_VEC2 +#define GL_INT_VEC2 0x8B53 +#endif +#ifndef GL_INT_VEC3 +#define GL_INT_VEC3 0x8B54 +#endif +#ifndef GL_INT_VEC4 +#define GL_INT_VEC4 0x8B55 +#endif +#ifndef GL_INVALID_ENUM +#define GL_INVALID_ENUM 0x0500 +#endif +#ifndef GL_INVALID_FRAMEBUFFER_OPERATION +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#endif +#ifndef GL_INVALID_OPERATION +#define GL_INVALID_OPERATION 0x0502 +#endif +#ifndef GL_INVALID_VALUE +#define GL_INVALID_VALUE 0x0501 +#endif +#ifndef GL_INVERT +#define GL_INVERT 0x150A +#endif +#ifndef GL_KEEP +#define GL_KEEP 0x1E00 +#endif +#ifndef GL_LEQUAL +#define GL_LEQUAL 0x0203 +#endif +#ifndef GL_LESS +#define GL_LESS 0x0201 +#endif +#ifndef GL_LINEAR +#define GL_LINEAR 0x2601 +#endif +#ifndef GL_LINEAR_MIPMAP_LINEAR +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#endif +#ifndef GL_LINEAR_MIPMAP_NEAREST +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#endif +#ifndef GL_LINE_LOOP +#define GL_LINE_LOOP 0x0002 +#endif +#ifndef GL_LINES +#define GL_LINES 0x0001 +#endif +#ifndef GL_LINE_STRIP +#define GL_LINE_STRIP 0x0003 +#endif +#ifndef GL_LINE_WIDTH +#define GL_LINE_WIDTH 0x0B21 +#endif +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif +#ifndef GL_LOW_FLOAT +#define GL_LOW_FLOAT 0x8DF0 +#endif +#ifndef GL_LOW_INT +#define GL_LOW_INT 0x8DF3 +#endif +#ifndef GL_LUMINANCE +#define GL_LUMINANCE 0x1909 +#endif +#ifndef GL_LUMINANCE_ALPHA +#define GL_LUMINANCE_ALPHA 0x190A +#endif +#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#endif +#ifndef GL_MAX_CUBE_MAP_TEXTURE_SIZE +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#endif +#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#endif +#ifndef GL_MAX_RENDERBUFFER_SIZE +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#endif +#ifndef GL_MAX_TEXTURE_IMAGE_UNITS +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#endif +#ifndef GL_MAX_TEXTURE_SIZE +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#endif +#ifndef GL_MAX_VARYING_VECTORS +#define GL_MAX_VARYING_VECTORS 0x8DFC +#endif +#ifndef GL_MAX_VERTEX_ATTRIBS +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#endif +#ifndef GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#endif +#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#endif +#ifndef GL_MAX_VIEWPORT_DIMS +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#endif +#ifndef GL_MEDIUM_FLOAT +#define GL_MEDIUM_FLOAT 0x8DF1 +#endif +#ifndef GL_MEDIUM_INT +#define GL_MEDIUM_INT 0x8DF4 +#endif +#ifndef GL_MIRRORED_REPEAT +#define GL_MIRRORED_REPEAT 0x8370 +#endif +#ifndef GL_NEAREST +#define GL_NEAREST 0x2600 +#endif +#ifndef GL_NEAREST_MIPMAP_LINEAR +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#endif +#ifndef GL_NEAREST_MIPMAP_NEAREST +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#endif +#ifndef GL_NEVER +#define GL_NEVER 0x0200 +#endif +#ifndef GL_NICEST +#define GL_NICEST 0x1102 +#endif +#ifndef GL_NO_ERROR +#define GL_NO_ERROR 0 +#endif +#ifndef GL_NONE +#define GL_NONE 0 +#endif +#ifndef GL_NOTEQUAL +#define GL_NOTEQUAL 0x0205 +#endif +#ifndef GL_NUM_COMPRESSED_TEXTURE_FORMATS +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#endif +#ifndef GL_NUM_SHADER_BINARY_FORMATS +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#endif +#ifndef GL_ONE +#define GL_ONE 1 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_ALPHA +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_COLOR +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#endif +#ifndef GL_ONE_MINUS_DST_ALPHA +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#endif +#ifndef GL_ONE_MINUS_DST_COLOR +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#endif +#ifndef GL_ONE_MINUS_SRC_ALPHA +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#endif +#ifndef GL_ONE_MINUS_SRC_COLOR +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#endif +#ifndef GL_OUT_OF_MEMORY +#define GL_OUT_OF_MEMORY 0x0505 +#endif +#ifndef GL_PACK_ALIGNMENT +#define GL_PACK_ALIGNMENT 0x0D05 +#endif +#ifndef GL_POINTS +#define GL_POINTS 0x0000 +#endif +#ifndef GL_POLYGON_OFFSET_FACTOR +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#endif +#ifndef GL_POLYGON_OFFSET_FILL +#define GL_POLYGON_OFFSET_FILL 0x8037 +#endif +#ifndef GL_POLYGON_OFFSET_UNITS +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#endif +#ifndef GL_RED_BITS +#define GL_RED_BITS 0x0D52 +#endif +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER 0x8D41 +#endif +#ifndef GL_RENDERBUFFER_ALPHA_SIZE +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#endif +#ifndef GL_RENDERBUFFER_BINDING +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#endif +#ifndef GL_RENDERBUFFER_BLUE_SIZE +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#endif +#ifndef GL_RENDERBUFFER_DEPTH_SIZE +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#endif +#ifndef GL_RENDERBUFFER_GREEN_SIZE +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#endif +#ifndef GL_RENDERBUFFER_HEIGHT +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#endif +#ifndef GL_RENDERBUFFER_INTERNAL_FORMAT +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#endif +#ifndef GL_RENDERBUFFER_RED_SIZE +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#endif +#ifndef GL_RENDERBUFFER_STENCIL_SIZE +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#endif +#ifndef GL_RENDERBUFFER_WIDTH +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#endif +#ifndef GL_RENDERER +#define GL_RENDERER 0x1F01 +#endif +#ifndef GL_REPEAT +#define GL_REPEAT 0x2901 +#endif +#ifndef GL_REPLACE +#define GL_REPLACE 0x1E01 +#endif +#ifndef GL_RGB +#define GL_RGB 0x1907 +#endif +#ifndef GL_RGB565 +#define GL_RGB565 0x8D62 +#endif +#ifndef GL_RGB5_A1 +#define GL_RGB5_A1 0x8057 +#endif +#ifndef GL_RGBA +#define GL_RGBA 0x1908 +#endif +#ifndef GL_RGBA4 +#define GL_RGBA4 0x8056 +#endif +#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#endif +#ifndef GL_SAMPLE_BUFFERS +#define GL_SAMPLE_BUFFERS 0x80A8 +#endif +#ifndef GL_SAMPLE_COVERAGE +#define GL_SAMPLE_COVERAGE 0x80A0 +#endif +#ifndef GL_SAMPLE_COVERAGE_INVERT +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#endif +#ifndef GL_SAMPLE_COVERAGE_VALUE +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#endif +#ifndef GL_SAMPLER_2D +#define GL_SAMPLER_2D 0x8B5E +#endif +#ifndef GL_SAMPLER_CUBE +#define GL_SAMPLER_CUBE 0x8B60 +#endif +#ifndef GL_SAMPLES +#define GL_SAMPLES 0x80A9 +#endif +#ifndef GL_SCISSOR_BOX +#define GL_SCISSOR_BOX 0x0C10 +#endif +#ifndef GL_SCISSOR_TEST +#define GL_SCISSOR_TEST 0x0C11 +#endif +#ifndef GL_SHADER_BINARY_FORMATS +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#endif +#ifndef GL_SHADER_COMPILER +#define GL_SHADER_COMPILER 0x8DFA +#endif +#ifndef GL_SHADER_SOURCE_LENGTH +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#endif +#ifndef GL_SHADER_TYPE +#define GL_SHADER_TYPE 0x8B4F +#endif +#ifndef GL_SHADING_LANGUAGE_VERSION +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#endif +#ifndef GL_SHORT +#define GL_SHORT 0x1402 +#endif +#ifndef GL_SRC_ALPHA +#define GL_SRC_ALPHA 0x0302 +#endif +#ifndef GL_SRC_ALPHA_SATURATE +#define GL_SRC_ALPHA_SATURATE 0x0308 +#endif +#ifndef GL_SRC_COLOR +#define GL_SRC_COLOR 0x0300 +#endif +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT 0x8D20 +#endif +#ifndef GL_STENCIL_BACK_FAIL +#define GL_STENCIL_BACK_FAIL 0x8801 +#endif +#ifndef GL_STENCIL_BACK_FUNC +#define GL_STENCIL_BACK_FUNC 0x8800 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_FAIL +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_PASS +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#endif +#ifndef GL_STENCIL_BACK_REF +#define GL_STENCIL_BACK_REF 0x8CA3 +#endif +#ifndef GL_STENCIL_BACK_VALUE_MASK +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#endif +#ifndef GL_STENCIL_BACK_WRITEMASK +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#endif +#ifndef GL_STENCIL_BITS +#define GL_STENCIL_BITS 0x0D57 +#endif +#ifndef GL_STENCIL_BUFFER_BIT +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#endif +#ifndef GL_STENCIL_CLEAR_VALUE +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#endif +#ifndef GL_STENCIL_FAIL +#define GL_STENCIL_FAIL 0x0B94 +#endif +#ifndef GL_STENCIL_FUNC +#define GL_STENCIL_FUNC 0x0B92 +#endif +#ifndef GL_STENCIL_INDEX +#define GL_STENCIL_INDEX 0x1901 +#endif +#ifndef GL_STENCIL_INDEX8 +#define GL_STENCIL_INDEX8 0x8D48 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_FAIL +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_PASS +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#endif +#ifndef GL_STENCIL_REF +#define GL_STENCIL_REF 0x0B97 +#endif +#ifndef GL_STENCIL_TEST +#define GL_STENCIL_TEST 0x0B90 +#endif +#ifndef GL_STENCIL_VALUE_MASK +#define GL_STENCIL_VALUE_MASK 0x0B93 +#endif +#ifndef GL_STENCIL_WRITEMASK +#define GL_STENCIL_WRITEMASK 0x0B98 +#endif +#ifndef GL_STREAM_DRAW +#define GL_STREAM_DRAW 0x88E0 +#endif +#ifndef GL_SUBPIXEL_BITS +#define GL_SUBPIXEL_BITS 0x0D50 +#endif +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif +#ifndef GL_TEXTURE10 +#define GL_TEXTURE10 0x84CA +#endif +#ifndef GL_TEXTURE1 +#define GL_TEXTURE1 0x84C1 +#endif +#ifndef GL_TEXTURE11 +#define GL_TEXTURE11 0x84CB +#endif +#ifndef GL_TEXTURE12 +#define GL_TEXTURE12 0x84CC +#endif +#ifndef GL_TEXTURE13 +#define GL_TEXTURE13 0x84CD +#endif +#ifndef GL_TEXTURE14 +#define GL_TEXTURE14 0x84CE +#endif +#ifndef GL_TEXTURE15 +#define GL_TEXTURE15 0x84CF +#endif +#ifndef GL_TEXTURE16 +#define GL_TEXTURE16 0x84D0 +#endif +#ifndef GL_TEXTURE17 +#define GL_TEXTURE17 0x84D1 +#endif +#ifndef GL_TEXTURE18 +#define GL_TEXTURE18 0x84D2 +#endif +#ifndef GL_TEXTURE19 +#define GL_TEXTURE19 0x84D3 +#endif +#ifndef GL_TEXTURE20 +#define GL_TEXTURE20 0x84D4 +#endif +#ifndef GL_TEXTURE2 +#define GL_TEXTURE2 0x84C2 +#endif +#ifndef GL_TEXTURE21 +#define GL_TEXTURE21 0x84D5 +#endif +#ifndef GL_TEXTURE22 +#define GL_TEXTURE22 0x84D6 +#endif +#ifndef GL_TEXTURE23 +#define GL_TEXTURE23 0x84D7 +#endif +#ifndef GL_TEXTURE24 +#define GL_TEXTURE24 0x84D8 +#endif +#ifndef GL_TEXTURE25 +#define GL_TEXTURE25 0x84D9 +#endif +#ifndef GL_TEXTURE26 +#define GL_TEXTURE26 0x84DA +#endif +#ifndef GL_TEXTURE27 +#define GL_TEXTURE27 0x84DB +#endif +#ifndef GL_TEXTURE28 +#define GL_TEXTURE28 0x84DC +#endif +#ifndef GL_TEXTURE29 +#define GL_TEXTURE29 0x84DD +#endif +#ifndef GL_TEXTURE_2D +#define GL_TEXTURE_2D 0x0DE1 +#endif +#ifndef GL_TEXTURE30 +#define GL_TEXTURE30 0x84DE +#endif +#ifndef GL_TEXTURE3 +#define GL_TEXTURE3 0x84C3 +#endif +#ifndef GL_TEXTURE31 +#define GL_TEXTURE31 0x84DF +#endif +#ifndef GL_TEXTURE4 +#define GL_TEXTURE4 0x84C4 +#endif +#ifndef GL_TEXTURE5 +#define GL_TEXTURE5 0x84C5 +#endif +#ifndef GL_TEXTURE6 +#define GL_TEXTURE6 0x84C6 +#endif +#ifndef GL_TEXTURE7 +#define GL_TEXTURE7 0x84C7 +#endif +#ifndef GL_TEXTURE8 +#define GL_TEXTURE8 0x84C8 +#endif +#ifndef GL_TEXTURE9 +#define GL_TEXTURE9 0x84C9 +#endif +#ifndef GL_TEXTURE_BINDING_2D +#define GL_TEXTURE_BINDING_2D 0x8069 +#endif +#ifndef GL_TEXTURE_BINDING_CUBE_MAP +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#endif +#ifndef GL_TEXTURE_CUBE_MAP +#define GL_TEXTURE_CUBE_MAP 0x8513 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Y +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Y +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Z +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#endif +#ifndef GL_TEXTURE_MAG_FILTER +#define GL_TEXTURE_MAG_FILTER 0x2800 +#endif +#ifndef GL_TEXTURE_MIN_FILTER +#define GL_TEXTURE_MIN_FILTER 0x2801 +#endif +#ifndef GL_TEXTURE_WRAP_S +#define GL_TEXTURE_WRAP_S 0x2802 +#endif +#ifndef GL_TEXTURE_WRAP_T +#define GL_TEXTURE_WRAP_T 0x2803 +#endif +#ifndef GL_TRIANGLE_FAN +#define GL_TRIANGLE_FAN 0x0006 +#endif +#ifndef GL_TRIANGLES +#define GL_TRIANGLES 0x0004 +#endif +#ifndef GL_TRIANGLE_STRIP +#define GL_TRIANGLE_STRIP 0x0005 +#endif +#ifndef GL_TRUE +#define GL_TRUE 1 +#endif +#ifndef GL_UNPACK_ALIGNMENT +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#endif +#ifndef GL_UNSIGNED_BYTE +#define GL_UNSIGNED_BYTE 0x1401 +#endif +#ifndef GL_UNSIGNED_INT +#define GL_UNSIGNED_INT 0x1405 +#endif +#ifndef GL_UNSIGNED_SHORT +#define GL_UNSIGNED_SHORT 0x1403 +#endif +#ifndef GL_UNSIGNED_SHORT_4_4_4_4 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#endif +#ifndef GL_UNSIGNED_SHORT_5_5_5_1 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#endif +#ifndef GL_UNSIGNED_SHORT_5_6_5 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#endif +#ifndef GL_VALIDATE_STATUS +#define GL_VALIDATE_STATUS 0x8B83 +#endif +#ifndef GL_VENDOR +#define GL_VENDOR 0x1F00 +#endif +#ifndef GL_VERSION +#define GL_VERSION 0x1F02 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_NORMALIZED +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_POINTER +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_SIZE +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_STRIDE +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_TYPE +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif +#ifndef GL_VIEWPORT +#define GL_VIEWPORT 0x0BA2 +#endif +#ifndef GL_ZERO +#define GL_ZERO 0 +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 9a8b243..3d9cd21 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -388,25 +388,25 @@ bool QGLPixelBuffer::isValid() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ QPaintEngine *QGLPixelBuffer::paintEngine() const { #if defined(QT_OPENGL_ES_1) - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); else - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #endif } diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp index 8d0d105..df83566 100644 --- a/src/opengl/qglpixelbuffer_win.cpp +++ b/src/opengl/qglpixelbuffer_win.cpp @@ -239,8 +239,7 @@ static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { - QGLWidget dmy; - dmy.makeCurrent(); // needed for wglGetProcAddress() to succeed + QGLTemporaryContext tempContext; PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); @@ -254,7 +253,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge if (!wglCreatePbufferARB) // assumes that if one can be resolved, all of them can return false; - dc = GetDC(dmy.winId()); + dc = wglGetCurrentDC(); Q_ASSERT(dc); PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = @@ -284,7 +283,6 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge if (num_formats == 0) { qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer - giving up."); - ReleaseDC(dmy.winId(), dc); return false; } format = pfiToQGLFormat(dc, pixel_format); @@ -303,12 +301,10 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge has_render_texture = false; if (!pbuf) { qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); - ReleaseDC(dmy.winId(), dc); return false; } } - ReleaseDC(dmy.winId(), dc); dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index bfa5ef1..68586c1 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -315,7 +315,7 @@ class QGLBlurTextureCache : public QObject public: static QGLBlurTextureCache *cacheForContext(const QGLContext *context); - QGLBlurTextureCache(); + QGLBlurTextureCache(const QGLContext *); ~QGLBlurTextureCache(); QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap); @@ -336,15 +336,9 @@ private: }; QList<QGLBlurTextureCache *> QGLBlurTextureCache::blurTextureCaches; +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLBlurTextureCache>, qt_blur_texture_caches) -static void QGLBlurTextureCache_free(void *ptr) -{ - delete reinterpret_cast<QGLBlurTextureCache *>(ptr); -} - -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_blur_texture_caches, (QGLBlurTextureCache_free)) - -QGLBlurTextureCache::QGLBlurTextureCache() +QGLBlurTextureCache::QGLBlurTextureCache(const QGLContext *) : timerId(0) { cache.setMaxCost(4 * 1024 * 1024); @@ -366,12 +360,7 @@ void QGLBlurTextureCache::timerEvent(QTimerEvent *) QGLBlurTextureCache *QGLBlurTextureCache::cacheForContext(const QGLContext *context) { - QGLBlurTextureCache *p = reinterpret_cast<QGLBlurTextureCache *>(qt_blur_texture_caches()->value(context)); - if (!p) { - p = new QGLBlurTextureCache; - qt_blur_texture_caches()->insert(context, p); - } - return p; + return qt_blur_texture_caches()->value(context); } QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixmap) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 0e6e773..0d2425f 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -77,7 +77,8 @@ extern int qt_vg_pixmap_serial; static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) { - CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + CFbsBitmap *copy = new CFbsBitmap; + Q_CHECK_PTR(copy); if(!copy) return 0; @@ -255,7 +256,8 @@ void* QVGPixmapData::toNativeType(NativeType type) sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; - RSgImage *sgImage = q_check_ptr(new RSgImage()); + RSgImage *sgImage = new RSgImage(); + Q_CHECK_PTR(sgImage); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); @@ -297,7 +299,8 @@ void* QVGPixmapData::toNativeType(NativeType type) return reinterpret_cast<void*>(sgImage); #endif } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + CFbsBitmap *bitmap = new CFbsBitmap; + Q_CHECK_PTR(bitmap); if (bitmap) { if (bitmap->Create(TSize(source.width(), source.height()), diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 662663d..6eb0617 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -348,7 +348,7 @@ QVariant QAccessibleTextEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/plugins/accessible/widgets/rangecontrols.cpp index 4cd171b..bf7b561 100644 --- a/src/plugins/accessible/widgets/rangecontrols.cpp +++ b/src/plugins/accessible/widgets/rangecontrols.cpp @@ -233,7 +233,7 @@ QVariant QAccessibleAbstractSpinBox::invokeMethodEx(Method method, int child, co case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: @@ -814,7 +814,7 @@ QVariant QAccessibleAbstractSlider::invokeMethodEx(Method method, int child, con case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index f39d538..d8b57af 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -732,7 +732,7 @@ QVariant QAccessibleLineEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 3722c43..3fc0bae 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -1045,7 +1045,7 @@ QVariantMap QConnmanDeviceInterface::getProperties() bool QConnmanDeviceInterface::setProperty(const QString &name, const QDBusVariant &value) { - QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, qVariantFromValue(value)); + QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, QVariant::fromValue(value)); return true; } @@ -1107,7 +1107,7 @@ quint16 QConnmanDeviceInterface::getScanInterval() bool QConnmanDeviceInterface::setScanInterval(const QString & interval) { // QList<QVariant> args; -// args << qVariantFromValue(name) +// args << QVariant::fromValue(name) // << value.variant(); // QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); @@ -1130,8 +1130,8 @@ QStringList QConnmanDeviceInterface::getNetworks() bool QConnmanDeviceInterface::setEnabled(bool powered) { QList<QVariant> args; - args << qVariantFromValue(QString("Powered")) - << qVariantFromValue(QDBusVariant(powered)); + args << QVariant::fromValue(QString("Powered")) + << QVariant::fromValue(QDBusVariant(powered)); QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); return true; diff --git a/src/plugins/gfxdrivers/eglnullws/README b/src/plugins/gfxdrivers/eglnullws/README new file mode 100644 index 0000000..80b88c7 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/README @@ -0,0 +1,48 @@ +EGL NullWS QScreen Driver +========================= + +If your application draws everything within a single full-screen QGLWidget then +you may wish to use this QScreen plugin driver. This driver simply returns 0 +(as a EGLNativeWindowType value) when asked by the QtOpenGl module to create a +native window. Some OpenGL ES implementations (including PowerVR) interpret this +to mean that a full-screen OpenGL context is desired without any windowing +support (NullWS). + +To tell a Qt/Embedded application to use this driver use the -display command +line option or the QWS_DISPLAY environment variable. The following driver +options are supported: + +size=WIDTHxHEIGHT Screen size reported by the driver +format=FORMAT Screen format + +Run with '-display eglnullws:help' to get a full list of options (including a +list of supported format strings). + +If you choose a screen format that is not supported by the hardware then the +QtOpenGl module will write out a list of supported EGL configurations. Use +one of the supported screen formats from this list. + +Using this driver with PowerVR hardware +--------------------------------------- + +Using this plugin with PowerVR hardware should give a significant speedup +compared to running with the Qt powervr driver (with a full-screen QGLWidget). +This is because sacrificing the window system allows less work to be done in +order to get graphics on the screen. Using this driver also avoids the memory +fragmentation issues present in the powervr driver and avoids any direct +dependencies on the deprecated PVR2D API from Imagination Technologies. + +To use this driver ensure you have /etc/powervr.ini with contents similar to +this: + +[default] +WindowSystem=libpvrPVR2D_FLIPWSEGL.so + +This driver will also function with libpvrPVR2D_FRONTWSEGL.so, but that draws +straight into the framebuffer and will therefore cause flickering (it can be +useful for performance testing though). The flip plugin uses triple buffering, +so you will need to set the virtual vertical resolution of your framebuffer to +be three times the physical vertical resolution of your screen. This can be +done with 'fbset -vyres'. Failure to do this can cause system crashes. You +should also ensure that the plugin you choose in powervr.ini is in your library +path (it may just silently default to the flip plugin if not). diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullws.pro b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro new file mode 100644 index 0000000..242ab07 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro @@ -0,0 +1,18 @@ +TARGET = qeglnullws +include(../../qpluginbase.pri) + +CONFIG += warn_on +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers + +target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers +INSTALLS += target + +HEADERS = eglnullwsscreen.h \ + eglnullwsscreenplugin.h \ + eglnullwswindowsurface.h + +SOURCES = eglnullwsscreen.cpp \ + eglnullwsscreenplugin.cpp \ + eglnullwswindowsurface.cpp diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp new file mode 100644 index 0000000..b8ea5d5 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwsscreen.h" +#include "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QHash> +#include <QDebug> + +namespace +{ + class EGLNullWSScreenSurfaceFunctions : public QGLScreenSurfaceFunctions + { + public: + virtual bool createNativeWindow(QWidget *, EGLNativeWindowType *native) + { *native = 0; return true; } + }; +} + +EGLNullWSScreen::EGLNullWSScreen(int displayId) : QGLScreen(displayId) {} + +EGLNullWSScreen::~EGLNullWSScreen() {} + +bool EGLNullWSScreen::initDevice() +{ + setSurfaceFunctions(new EGLNullWSScreenSurfaceFunctions); + return true; +} + +static const QHash<QString, QImage::Format> formatDictionary() +{ + QHash<QString, QImage::Format> dictionary; + dictionary["rgb32"] = QImage::Format_RGB32; + dictionary["argb32"] = QImage::Format_ARGB32; + dictionary["rgb16"] = QImage::Format_RGB16; + dictionary["rgb666"] = QImage::Format_RGB666; + dictionary["rgb555"] = QImage::Format_RGB555; + dictionary["rgb888"] = QImage::Format_RGB888; + dictionary["rgb444"] = QImage::Format_RGB444; + return dictionary; +} + +static int depthForFormat(QImage::Format format) +{ + switch (format) { + case QImage::Format_RGB32: return 32; + case QImage::Format_ARGB32: return 32; + case QImage::Format_RGB16: return 16; + case QImage::Format_RGB666: return 24; + case QImage::Format_RGB555: return 16; + case QImage::Format_RGB888: return 24; + case QImage::Format_RGB444: return 16; + default: + Q_ASSERT_X(false, "EGLNullWSScreen", "Unknown format"); + return -1; + } +} + +static void printHelp(const QHash<QString, QImage::Format> &formatDictionary) +{ + QByteArray formatsBuf; + QTextStream(&formatsBuf) << QStringList(formatDictionary.keys()).join(", "); + qWarning( + "%s: Valid options are:\n" + "size=WIDTHxHEIGHT Screen size reported by this driver\n" + "format=FORMAT Screen format, where FORMAT is one of the following:\n" + " %s\n", + PluginName, + formatsBuf.constData()); +} + +bool EGLNullWSScreen::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.section(':', 1).split(':', QString::SkipEmptyParts); + const QHash<QString, QImage::Format> formatDict = formatDictionary(); + Q_FOREACH(const QString arg, args) { + const QString optionName = arg.section('=', 0, 0); + const QString optionArg = arg.section('=', 1); + if (optionName == QLatin1String("size")) { + w = optionArg.section('x', 0, 0).toInt(); + h = optionArg.section('x', 1, 1).toInt(); + } else if (optionName == QLatin1String("format")) { + if (formatDict.contains(optionArg)) + setPixelFormat(formatDict.value(optionArg)); + else + printHelp(formatDict); + } else { + printHelp(formatDict); + } + } + + if (w == 0 || h == 0) { + w = 640; + h = 480; + qWarning("%s: Using default screen size %dx%d", PluginName, w, h); + } + dw = w; + dh = h; + + if (pixelFormat() == QImage::Format_Invalid) { + qWarning("%s: Using default screen format argb32", PluginName); + setPixelFormat(QImage::Format_ARGB32); + } + d = depthForFormat(pixelFormat()); + + static const int Dpi = 120; + static const qreal ScalingFactor = static_cast<qreal>(25.4) / Dpi; + physWidth = qRound(dw * ScalingFactor); + physHeight = qRound(dh * ScalingFactor); + + return true; +} + +void EGLNullWSScreen::disconnect() {} + +void EGLNullWSScreen::shutdownDevice() {} + +void EGLNullWSScreen::setMode(int /*width*/, int /*height*/, int /*depth*/) {} + +void EGLNullWSScreen::blank(bool /*on*/) {} + +void EGLNullWSScreen::exposeRegion(QRegion /*r*/, int /*changing*/) {} + +QWSWindowSurface* EGLNullWSScreen::createSurface(QWidget *widget) const +{ + if (qobject_cast<QGLWidget*>(widget)) { + return new EGLNullWSWindowSurface(widget); + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(widget); + } +} + +QWSWindowSurface* EGLNullWSScreen::createSurface(const QString &key) const +{ + if (key == QLatin1String("eglnullws")) { + return new EGLNullWSWindowSurface; + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(key); + } +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h new file mode 100644 index 0000000..7f794bc --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREEN +#define EGLNULLWSSCREEN + +#include <QGLScreen> + +class EGLNullWSScreen : public QGLScreen +{ +public: + EGLNullWSScreen(int displayId); + ~EGLNullWSScreen(); + + bool initDevice(); + bool connect(const QString &displaySpec); + void disconnect(); + void shutdownDevice(); + + void setMode(int width, int height, int depth); + void blank(bool on); + + void exposeRegion(QRegion r, int changing); + + QWSWindowSurface* createSurface(QWidget *widget) const; + QWSWindowSurface* createSurface(const QString &key) const; + + bool hasOpenGL() { return true; } +}; + +#endif // EGLNULLWSSCREEN diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp new file mode 100644 index 0000000..67b3f56 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwsscreenplugin.h" +#include "eglnullwsscreen.h" + +#include <QScreenDriverPlugin> +#include <QStringList> + +class EGLNullWSScreenPlugin : public QScreenDriverPlugin +{ +public: + virtual QStringList keys() const; + virtual QScreen *create(const QString& driver, int displayId); +}; + +QStringList EGLNullWSScreenPlugin::keys() const +{ + return QStringList() << QLatin1String(PluginName); +} + +QScreen *EGLNullWSScreenPlugin::create(const QString& driver, int displayId) +{ + return (driver.toLower() == QLatin1String(PluginName) ? + new EGLNullWSScreen(displayId) : 0); +} + +Q_EXPORT_PLUGIN2(qeglnullws, EGLNullWSScreenPlugin) diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h new file mode 100644 index 0000000..84f0699 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREENPLUGIN_H +#define EGLNULLWSSCREENPLUGIN_H + +const char *const PluginName = "eglnullws"; + +#endif // EGLNULLWSSCREENPLUGIN_H diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp new file mode 100644 index 0000000..da4b728 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QGLWidget> + +static const QWSWindowSurface::SurfaceFlags Flags + = QWSWindowSurface::RegionReserved | QWSWindowSurface::RegionReserved; + +EGLNullWSWindowSurface::EGLNullWSWindowSurface(QWidget *w) + : + QWSGLWindowSurface(w), + widget(w) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::EGLNullWSWindowSurface() + : widget(0) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::~EGLNullWSWindowSurface() {} + +QString EGLNullWSWindowSurface::key() const +{ + return QLatin1String(PluginName); +} + +QPaintDevice *EGLNullWSWindowSurface::paintDevice() +{ + return widget; +} + +bool EGLNullWSWindowSurface::isValid() const +{ + return qobject_cast<QGLWidget *>(window()); +} + +QImage EGLNullWSWindowSurface::image() const +{ + return QImage(); +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h new file mode 100644 index 0000000..b730415 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSWINDOWSURFACE_H +#define EGLNULLWSWINDOWSURFACE_H + +#include <private/qglwindowsurface_qws_p.h> + +class EGLNullWSWindowSurface : public QWSGLWindowSurface +{ +public: + EGLNullWSWindowSurface(QWidget *widget); + EGLNullWSWindowSurface(); + virtual ~EGLNullWSWindowSurface(); + + virtual QString key() const; + virtual QPaintDevice *paintDevice(); + virtual bool isValid() const; + virtual QImage image() const; + +private: + QWidget *widget; +}; + +#endif // EGLNULLWSWINDOWSURFACE_H diff --git a/src/plugins/gfxdrivers/gfxdrivers.pro b/src/plugins/gfxdrivers/gfxdrivers.pro index d1ee3f2..1f38942 100644 --- a/src/plugins/gfxdrivers/gfxdrivers.pro +++ b/src/plugins/gfxdrivers/gfxdrivers.pro @@ -7,3 +7,4 @@ contains(gfx-plugins, vnc) :SUBDIRS += vnc contains(gfx-plugins, transformed) :SUBDIRS += transformed contains(gfx-plugins, svgalib) :SUBDIRS += svgalib contains(gfx-plugins, powervr) :SUBDIRS += powervr +contains(gfx-plugins, eglnullws) :SUBDIRS += eglnullws diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 8b119b5..45e3976 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -1,6 +1,6 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.0 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qbase.pri b/src/qbase.pri index f6af22f..aa7d745 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -4,7 +4,7 @@ INCLUDEPATH *= $$QMAKE_INCDIR_QT/$$TARGET #just for today to have some compat isEmpty(QT_ARCH):!isEmpty(ARCH):QT_ARCH=$$ARCH #another compat that will rot for change #215700 TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.0 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp index 8614076..625dd95 100644 --- a/src/qt3support/text/q3richtext.cpp +++ b/src/qt3support/text/q3richtext.cpp @@ -8079,9 +8079,9 @@ bool Q3TextTable::down(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *& break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -8117,9 +8117,9 @@ bool Q3TextTable::up(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *&pa break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->lastParagraph(); idx = parag->length() - 1; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); diff --git a/src/qt3support/text/q3textstream.h b/src/qt3support/text/q3textstream.h index d0c4f48..0e26e08 100644 --- a/src/qt3support/text/q3textstream.h +++ b/src/qt3support/text/q3textstream.h @@ -272,13 +272,13 @@ private: int arg; // member function argument }; -Q_COMPAT_EXPORT inline Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) { m.exec(s); return s; } Q_COMPAT_EXPORT Q3TextStream &bin( Q3TextStream &s ); // set bin notation diff --git a/src/qt3support/tools/q3cstring.h b/src/qt3support/tools/q3cstring.h index b280ebc..86a31fa 100644 --- a/src/qt3support/tools/q3cstring.h +++ b/src/qt3support/tools/q3cstring.h @@ -161,75 +161,75 @@ inline Q3CString &Q3CString::setNum(float n, char f, int prec) Q3CString non-member operators *****************************************************************************/ -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const QByteArray &s2) { QByteArray tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const QByteArray &s1, const Q3CString &s2) { QByteArray tmp(s1); @@ -237,28 +237,28 @@ Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const char *s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const char *s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, char c2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, char c2) { Q3CString tmp(s1); tmp += c2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(char c1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(char c1, const Q3CString &s2) { Q3CString tmp; tmp += c1; diff --git a/src/s60main/qts60main.cpp b/src/s60main/qts60main.cpp index 5fbeea5..c65344b 100644 --- a/src/s60main/qts60main.cpp +++ b/src/s60main/qts60main.cpp @@ -51,7 +51,8 @@ GLDEF_C TInt QtMainWrapper(); */ GLDEF_C TInt E32Main() { - CTrapCleanup *cleanupStack = q_check_ptr(CTrapCleanup::New()); + CTrapCleanup *cleanupStack = CTrapCleanup::New(); + Q_CHECK_PTR(cleanupStack); TInt err = 0; TRAP(err, err = QtMainWrapper()); delete cleanupStack; diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 8560214..dc22ec3 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1706,7 +1706,7 @@ QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue valu return variantValue(value); #ifndef QT_NO_QOBJECT else if (isQObject(value)) - return qVariantFromValue(toQObject(exec, value)); + return QVariant::fromValue(toQObject(exec, value)); #endif else if (isDate(value)) return QVariant(toDateTime(exec, value)); @@ -2430,10 +2430,6 @@ QScriptValue QScriptEngine::newQMetaObject( \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 - \warning This function is not available with MSVC 6. Use - qScriptValueFromQMetaObject() instead if you need to support that version - of the compiler. - \sa QScriptEngine::newQMetaObject() */ @@ -2441,14 +2437,17 @@ QScriptValue QScriptEngine::newQMetaObject( \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine) \since 4.3 \relates QScriptEngine + \obsolete Uses \a engine to create a QScriptValue that represents the Qt class \c{T}. This function is equivalent to - QScriptEngine::scriptValueFromQMetaObject(). It is provided as a - work-around for MSVC 6, which doesn't support member template - functions. + QScriptEngine::scriptValueFromQMetaObject(). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QScriptEngine::newQMetaObject() */ @@ -2979,14 +2978,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const case QMetaType::LongLong: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); case QMetaType::ULongLong: -#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 -#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#else return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); -#endif case QMetaType::Double: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr))); case QMetaType::QString: @@ -3030,7 +3022,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const break; #endif case QMetaType::QVariant: - result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); + result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr)); break; default: if (type == qMetaTypeId<QScriptValue>()) { @@ -3744,10 +3736,6 @@ QStringList QScriptEngine::importedExtensions() const to newVariant()); you can change this behavior by installing your own type conversion functions with qScriptRegisterMetaType(). - \warning This function is not available with MSVC 6. Use - qScriptValueFromValue() instead if you need to support that - version of the compiler. - \sa fromScriptValue(), qScriptRegisterMetaType() */ @@ -3761,10 +3749,6 @@ QStringList QScriptEngine::importedExtensions() const description of the built-in type conversion provided by QtScript. - \warning This function is not available with MSVC 6. Use - qScriptValueToValue() or qscriptvalue_cast() instead if you need - to support that version of the compiler. - \sa toScriptValue(), qScriptRegisterMetaType() */ @@ -3772,29 +3756,35 @@ QStringList QScriptEngine::importedExtensions() const \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value) \since 4.3 \relates QScriptEngine + \obsolete Creates a QScriptValue using the given \a engine with the given \a value of template type \c{T}. This function is equivalent to QScriptEngine::toScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't support - member template functions. - \sa qScriptValueToValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::toScriptValue(), qscriptvalue_cast */ /*! \fn T qScriptValueToValue(const QScriptValue &value) \since 4.3 \relates QScriptEngine + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to QScriptEngine::fromScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't - support member template functions. - \sa qScriptValueFromValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::fromScriptValue() */ /*! @@ -3813,7 +3803,7 @@ QStringList QScriptEngine::importedExtensions() const \l{Conversion Between QtScript and C++ Types} for more information about the restrictions on types that can be used with QScriptValue. - \sa qScriptValueFromValue() + \sa QScriptEngine::fromScriptValue() */ /*! diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 3212ed5..830d477 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -65,13 +65,11 @@ inline QScriptValue qscriptQMetaObjectConstructor(QScriptContext *, QScriptEngin class QRegExp; #endif -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue qScriptValueFromValue(QScriptEngine *, const T &); template <typename T> -inline T qScriptValueToValue(const QScriptValue &); -#endif +inline T qscriptvalue_cast(const QScriptValue &); class QScriptSyntaxCheckResultPrivate; class Q_SCRIPT_EXPORT QScriptSyntaxCheckResult @@ -196,9 +194,7 @@ public: QScriptValue newQMetaObject(const QMetaObject *metaObject, const QScriptValue &ctor = QScriptValue()); -# ifndef QT_NO_MEMBER_TEMPLATES template <class T> QScriptValue scriptValueFromQMetaObject(); -# endif // QT_NO_MEMBER_TEMPLATES #endif // QT_NO_QOBJECT @@ -213,7 +209,6 @@ public: -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue toScriptValue(const T &value) { @@ -222,9 +217,8 @@ public: template <typename T> inline T fromScriptValue(const QScriptValue &value) { - return qScriptValueToValue<T>(value); + return qscriptvalue_cast<T>(value); } -#endif // QT_NO_MEMBER_TEMPLATES void installTranslatorFunctions(const QScriptValue &object = QScriptValue()); @@ -285,19 +279,6 @@ private: }; #ifndef QT_NO_QOBJECT -template <class T> -inline QScriptValue qScriptValueFromQMetaObject( - QScriptEngine *engine -#ifndef qdoc - , T * /* dummy */ = 0 -#endif - ) -{ - typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); - ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; - return engine->newQMetaObject(&T::staticMetaObject, - engine->newFunction(reinterpret_cast<QScriptEngine::FunctionWithArgSignature>(cptr), 0)); -} #define Q_SCRIPT_DECLARE_QMETAOBJECT(T, _Arg1) \ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext *ctx, QScriptEngine *eng, T *) \ @@ -311,12 +292,26 @@ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext * return o; \ } -# ifndef QT_NO_MEMBER_TEMPLATES - template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() - { - return qScriptValueFromQMetaObject<T>(this); - } -# endif // QT_NO_MEMBER_TEMPLATES +template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() +{ + typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); + ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; + return newQMetaObject(&T::staticMetaObject, + newFunction(reinterpret_cast<FunctionWithArgSignature>(cptr), 0)); +} + +#ifdef QT_DEPRECATED +template <class T> +inline QT_DEPRECATED QScriptValue qScriptValueFromQMetaObject( + QScriptEngine *engine +#ifndef qdoc + , T * /* dummy */ = 0 +#endif + ) +{ + return engine->scriptValueFromQMetaObject<T>(); +} +#endif #endif // QT_NO_QOBJECT @@ -349,11 +344,7 @@ inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void * } template<typename T> -T qscriptvalue_cast(const QScriptValue &value -#if !defined qdoc && defined Q_CC_MSVC && _MSC_VER < 1300 -, T * = 0 -#endif - ) +T qscriptvalue_cast(const QScriptValue &value) { T t; const int id = qMetaTypeId<T>(); @@ -366,19 +357,19 @@ T qscriptvalue_cast(const QScriptValue &value return T(); } -#if !defined Q_CC_MSVC || _MSC_VER >= 1300 template <> inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value) { return value.toVariant(); } -#endif +#ifdef QT_DEPRECATED template <typename T> -inline T qScriptValueToValue(const QScriptValue &value) +inline QT_DEPRECATED T qScriptValueToValue(const QScriptValue &value) { return qscriptvalue_cast<T>(value); } +#endif inline void qScriptRegisterMetaType_helper(QScriptEngine *eng, int type, QScriptEngine::MarshalFunction mf, @@ -418,7 +409,7 @@ QScriptValue qScriptValueFromSequence(QScriptEngine *eng, const Container &cont) typename Container::const_iterator it; quint32 i; for (it = begin, i = 0; it != end; ++it, ++i) - a.setProperty(i, qScriptValueFromValue(eng, *it)); + a.setProperty(i, eng->toScriptValue(*it)); return a; } @@ -428,11 +419,7 @@ void qScriptValueToSequence(const QScriptValue &value, Container &cont) quint32 len = value.property(QLatin1String("length")).toUInt32(); for (quint32 i = 0; i < len; ++i) { QScriptValue item = value.property(i); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - cont.push_back(qscriptvalue_cast<Container::value_type>(item)); -#else cont.push_back(qscriptvalue_cast<typename Container::value_type>(item)); -#endif } } diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index f6390bb..fbd5d96 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -688,10 +688,6 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) return false; case Number: -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(lhs.toNumber()) || qIsNaN(rhs.toNumber())) - return false; -#endif return lhs.toNumber() < rhs.toNumber(); case Boolean: @@ -714,13 +710,7 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) if (lhs.isString() && rhs.isString()) return lhs.toString() < rhs.toString(); - qsreal n1 = lhs.toNumber(); - qsreal n2 = rhs.toNumber(); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(n1) || qIsNaN(n2)) - return false; -#endif - return n1 < n2; + return lhs.toNumber() < rhs.toNumber(); } static bool Equals(QScriptValue lhs, QScriptValue rhs) diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index dd229f1..28f7bd1 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -211,7 +211,7 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC:: eng_p->pushContext(exec, thisValue, args, callee); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj); - QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); + QVariant result = scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx)); eng_p->popContext(); eng_p->currentFrame = oldFrame; return QScriptEnginePrivate::jscValueFromVariant(exec, result); @@ -239,7 +239,7 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue defaultObject = ctx->thisObject(); - QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); + QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx))); if (!result.isObject()) result = defaultObject; eng_p->popContext(); @@ -256,7 +256,7 @@ bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exe QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(eng_p, exec); args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); - QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); + QVariant result = scriptClass()->extension(QScriptClass::HasInstance, QVariant::fromValue(args)); return result.toBool(); } diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 5e4f097..d24f2fe 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -664,7 +664,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c if (actual.isNumber()) { int ival = QScriptEnginePrivate::toInt32(exec, actual); if (m.valueToKey(ival) != 0) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -672,7 +672,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c JSC::UString sval = QScriptEnginePrivate::toString(exec, actual); int ival = m.keyToValue(convertToLatin1(sval)); if (ival != -1) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -1668,7 +1668,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec QString name; if (args.size() != 0) name = args.at(0).toString(exec); - QObject *child = qFindChild<QObject*>(obj, name); + QObject *child = obj->findChild<QObject*>(name); QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; return engine->newQObject(child, QScriptEngine::QtOwnership, opt); } @@ -1709,10 +1709,10 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e } } else { const QString name(args.at(0).toString(exec)); - children = qFindChildren<QObject*>(obj, name); + children = obj->findChildren<QObject*>(name); } } else { - children = qFindChildren<QObject*>(obj, QString()); + children = obj->findChildren<QObject*>(QString()); } // create the result array with the children const int length = children.size(); diff --git a/src/scripttools/debugging/qscriptdebuggercommand.cpp b/src/scripttools/debugging/qscriptdebuggercommand.cpp index fa223ec..5ca0535 100644 --- a/src/scripttools/debugging/qscriptdebuggercommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommand.cpp @@ -256,7 +256,7 @@ QScriptBreakpointData QScriptDebuggerCommand::breakpointData() const void QScriptDebuggerCommand::setBreakpointData(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerCommand); - d->attributes[BreakpointData] = qVariantFromValue(data); + d->attributes[BreakpointData] = QVariant::fromValue(data); } QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const @@ -268,7 +268,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const void QScriptDebuggerCommand::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[ScriptValue] = qVariantFromValue(value); + d->attributes[ScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::contextIndex() const @@ -316,7 +316,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::subordinateScriptValue() const void QScriptDebuggerCommand::setSubordinateScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[SubordinateScriptValue] = qVariantFromValue(value); + d->attributes[SubordinateScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::snapshotId() const diff --git a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp index 568af59..7616148 100644 --- a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp @@ -229,11 +229,11 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( case QScriptDebuggerCommand::ScriptsCheckpoint: backend->scriptsCheckpoint(); - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::GetScriptsDelta: - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::ResolveScript: @@ -302,7 +302,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( } break; case QScriptDebuggerCommand::ContextsCheckpoint: { - response.setResult(qVariantFromValue(backend->contextsCheckpoint())); + response.setResult(QVariant::fromValue(backend->contextsCheckpoint())); } break; case QScriptDebuggerCommand::GetPropertyExpressionValue: { @@ -441,7 +441,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( result.addedProperties.append(dest); } backend->setIgnoreExceptions(didIgnoreExceptions); - response.setResult(qVariantFromValue(result)); + response.setResult(QVariant::fromValue(result)); } break; case QScriptDebuggerCommand::DeleteScriptObjectSnapshot: { diff --git a/src/scripttools/debugging/qscriptdebuggerconsole.cpp b/src/scripttools/debugging/qscriptdebuggerconsole.cpp index 2f7a998..268b30e 100644 --- a/src/scripttools/debugging/qscriptdebuggerconsole.cpp +++ b/src/scripttools/debugging/qscriptdebuggerconsole.cpp @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE static QScriptValue debuggerResponseToScriptValue(QScriptEngine *eng, const QScriptDebuggerResponse &in) { QScriptValue out = eng->newObject(); - out.setProperty(QString::fromLatin1("result"), qScriptValueFromValue(eng, in.result())); + out.setProperty(QString::fromLatin1("result"), eng->toScriptValue(in.result())); out.setProperty(QString::fromLatin1("error"), QScriptValue(eng, in.error())); out.setProperty(QString::fromLatin1("async"), QScriptValue(eng, in.async())); return out; @@ -122,7 +122,7 @@ static QScriptValue breakpointMapToScriptValue(QScriptEngine *eng, const QScript QScriptValue out = eng->newObject(); QScriptBreakpointMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -155,7 +155,7 @@ static QScriptValue scriptMapToScriptValue(QScriptEngine *eng, const QScriptScri QScriptValue out = eng->newObject(); QScriptScriptMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -175,8 +175,8 @@ static QScriptValue consoleCommandToScriptValue( out.setProperty(QString::fromLatin1("group"), QScriptValue(eng, in->group())); out.setProperty(QString::fromLatin1("shortDescription"), QScriptValue(eng, in->shortDescription())); out.setProperty(QString::fromLatin1("longDescription"), QScriptValue(eng, in->longDescription())); - out.setProperty(QString::fromLatin1("aliases"), qScriptValueFromValue(eng, in->aliases())); - out.setProperty(QString::fromLatin1("seeAlso"), qScriptValueFromValue(eng, in->seeAlso())); + out.setProperty(QString::fromLatin1("aliases"), eng->toScriptValue(in->aliases())); + out.setProperty(QString::fromLatin1("seeAlso"), eng->toScriptValue(in->seeAlso())); return out; } @@ -207,7 +207,7 @@ static QScriptValue consoleCommandGroupMapToScriptValue( QScriptValue out = eng->newObject(); QScriptDebuggerConsoleCommandGroupMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(it.key(), qScriptValueFromValue(eng, it.value())); + out.setProperty(it.key(), eng->toScriptValue(it.value())); } return out; } @@ -238,7 +238,7 @@ static QScriptValue debuggerScriptValuePropertyToScriptValue(QScriptEngine *eng, { QScriptValue out = eng->newObject(); out.setProperty(QString::fromLatin1("name"), QScriptValue(eng, in.name())); - out.setProperty(QString::fromLatin1("value"), qScriptValueFromValue(eng, in.value())); + out.setProperty(QString::fromLatin1("value"), eng->toScriptValue(in.value())); out.setProperty(QString::fromLatin1("valueAsString"), QScriptValue(eng, in.valueAsString())); out.setProperty(QString::fromLatin1("flags"), QScriptValue(eng, static_cast<int>(in.flags()))); return out; diff --git a/src/scripttools/debugging/qscriptdebuggerevent.cpp b/src/scripttools/debugging/qscriptdebuggerevent.cpp index f5f20cf..55df35b 100644 --- a/src/scripttools/debugging/qscriptdebuggerevent.cpp +++ b/src/scripttools/debugging/qscriptdebuggerevent.cpp @@ -216,7 +216,7 @@ QScriptDebuggerValue QScriptDebuggerEvent::scriptValue() const void QScriptDebuggerEvent::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerEvent); - d->attributes[Value] = qVariantFromValue(value); + d->attributes[Value] = QVariant::fromValue(value); } void QScriptDebuggerEvent::setNestedEvaluate(bool nested) diff --git a/src/scripttools/debugging/qscriptdebuggerresponse.cpp b/src/scripttools/debugging/qscriptdebuggerresponse.cpp index 0caa3e2..382e604e 100644 --- a/src/scripttools/debugging/qscriptdebuggerresponse.cpp +++ b/src/scripttools/debugging/qscriptdebuggerresponse.cpp @@ -162,49 +162,49 @@ void QScriptDebuggerResponse::setResult(const QString &value) void QScriptDebuggerResponse::setResult(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptBreakpointMap &breakpoints) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(breakpoints); + d->result = QVariant::fromValue(breakpoints); } void QScriptDebuggerResponse::setResult(const QScriptScriptMap &scripts) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(scripts); + d->result = QVariant::fromValue(scripts); } void QScriptDebuggerResponse::setResult(const QScriptScriptData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(value); + d->result = QVariant::fromValue(value); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValueList &values) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(values); + d->result = QVariant::fromValue(values); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValuePropertyList &props) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(props); + d->result = QVariant::fromValue(props); } void QScriptDebuggerResponse::setResult(const QScriptContextInfo &info) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(info); + d->result = QVariant::fromValue(info); } int QScriptDebuggerResponse::resultAsInt() const diff --git a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp index 117c2d6..83cabfd 100644 --- a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp @@ -227,7 +227,7 @@ void QScriptDebuggerScriptedConsoleCommandJob::handleResponse( QScriptEngine *engine = d->command->globalObject.engine(); engine->setGlobalObject(d->command->globalObject); QScriptValueList args; - args.append(qScriptValueFromValue(engine, response)); + args.append(engine->toScriptValue(response)); args.append(QScriptValue(engine, commandId)); QScriptDebuggerConsoleGlobalObject *global; global = qobject_cast<QScriptDebuggerConsoleGlobalObject*>(d->command->globalObject.toQObject()); diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 2261887..a060a01 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -420,10 +420,10 @@ QVariant QMYSQLResult::handle() const { #if MYSQL_VERSION_ID >= 40108 if(d->preparedQuery) - return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt); + return d->meta ? QVariant::fromValue(d->meta) : qVariantFromValue(d->stmt); else #endif - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QMYSQLResult::cleanup() @@ -1432,7 +1432,7 @@ QSqlRecord QMYSQLDriver::record(const QString& tablename) const QVariant QMYSQLDriver::handle() const { - return qVariantFromValue(d->mysql); + return QVariant::fromValue(d->mysql); } bool QMYSQLDriver::beginTransaction() diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index e11cf75..6870055 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -293,9 +293,9 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in SQLT_FLT, indPtr, 0, 0, 0, 0, OCI_DEFAULT); break; case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val) && !isOutValue(pos)) { + if (val.canConvert<QOCIRowIdPointer>() && !isOutValue(pos)) { // use a const pointer to prevent a detach - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); r = OCIBindByPos(sql, hbnd, err, pos + 1, // it's an IN value, so const_cast is ok @@ -1364,8 +1364,8 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b break; } case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val)) { - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + if (val.canConvert<QOCIRowIdPointer>()) { + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); *reinterpret_cast<OCIRowid**>(dataPtr) = rptr->id; columns[i].lengths[row] = 0; break; @@ -1704,7 +1704,7 @@ QOCIResult::~QOCIResult() QVariant QOCIResult::handle() const { - return qVariantFromValue(d->sql); + return QVariant::fromValue(d->sql); } bool QOCIResult::reset (const QString& query) @@ -1932,7 +1932,7 @@ QVariant QOCIResult::lastInsertId() const int r = OCIAttrGet(d->sql, OCI_HTYPE_STMT, ptr.constData()->id, 0, OCI_ATTR_ROWID, d->err); if (r == OCI_SUCCESS) - return qVariantFromValue(ptr); + return QVariant::fromValue(ptr); } return QVariant(); } @@ -2534,7 +2534,7 @@ QString QOCIDriver::formatValue(const QSqlField &field, bool trimStrings) const QVariant QOCIDriver::handle() const { - return qVariantFromValue(d->env); + return QVariant::fromValue(d->env); } QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 9a35ac5..cc73f1b 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -62,15 +62,6 @@ QT_BEGIN_NAMESPACE // undefine this to prevent initial check of the ODBC driver #define ODBC_CHECK_DRIVER -// newer platform SDKs use SQLLEN instead of SQLINTEGER -#if defined(WIN32) && (_MSC_VER < 1300) && !defined(__MINGW64_VERSION_MAJOR) -# define QSQLLEN SQLINTEGER -# define QSQLULEN SQLUINTEGER -#else -# define QSQLLEN SQLLEN -# define QSQLULEN SQLULEN -#endif - static const int COLNAMESIZE = 256; //Map Qt parameter types to ODBC types static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; @@ -360,7 +351,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni { QString fieldVal; SQLRETURN r = SQL_ERROR; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; // NB! colSize must be a multiple of 2 for unicode enabled DBs if (colSize <= 0) { @@ -462,10 +453,10 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) QByteArray fieldVal; SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQL_ERROR; QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE); @@ -499,7 +490,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) break; if (lengthIndicator == SQL_NULL_DATA) return QVariant(QVariant::ByteArray); - if (lengthIndicator > QSQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { + if (lengthIndicator > SQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { read += colSize; colSize = 65536; } else { @@ -517,7 +508,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLINTEGER intbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SLONG : SQL_C_ULONG, @@ -537,7 +528,7 @@ static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) { SQLDOUBLE dblbuf; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, SQL_C_DOUBLE, @@ -557,7 +548,7 @@ static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLBIGINT lngbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT, @@ -601,7 +592,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) { SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; @@ -621,7 +612,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) return QSqlField(); } - QSQLLEN unsignedFlag = SQL_FALSE; + SQLLEN unsignedFlag = SQL_FALSE; r = SQLColAttribute (p->hStmt, i + 1, SQL_DESC_UNSIGNED, @@ -1146,7 +1137,7 @@ QVariant QODBCResult::data(int field) return d->fieldCache.at(field); SQLRETURN r(0); - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; for (int i = d->fieldCacheIdx; i <= field; ++i) { // some servers do not support fetching column n after we already @@ -1256,7 +1247,7 @@ int QODBCResult::size() int QODBCResult::numRowsAffected() { - QSQLLEN affectedRowCount = 0; + SQLLEN affectedRowCount = 0; SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); if (r == SQL_SUCCESS) return affectedRowCount; @@ -1343,8 +1334,8 @@ bool QODBCResult::exec() SQLCloseCursor(d->hStmt); QList<QByteArray> tmpStorage; // holds temporary buffers - QVarLengthArray<QSQLLEN, 32> indicators(boundValues().count()); - memset(indicators.data(), 0, indicators.size() * sizeof(QSQLLEN)); + QVarLengthArray<SQLLEN, 32> indicators(boundValues().count()); + memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); // bind parameters - only positional binding allowed QVector<QVariant>& values = boundValues(); @@ -1354,7 +1345,7 @@ bool QODBCResult::exec() if (bindValueType(i) & QSql::Out) values[i].detach(); const QVariant &val = values.at(i); - QSQLLEN *ind = &indicators[i]; + SQLLEN *ind = &indicators[i]; if (val.isNull()) *ind = SQL_NULL_DATA; switch (val.type()) { diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 2a4e595..179f7ba 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -279,7 +279,7 @@ QPSQLResult::~QPSQLResult() QVariant QPSQLResult::handle() const { - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QPSQLResult::cleanup() @@ -706,7 +706,7 @@ QPSQLDriver::~QPSQLDriver() QVariant QPSQLDriver::handle() const { - return qVariantFromValue(d->connection); + return QVariant::fromValue(d->connection); } bool QPSQLDriver::hasFeature(DriverFeature f) const diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 4344af4..e5cc614 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -452,7 +452,7 @@ QSqlRecord QSQLiteResult::record() const QVariant QSQLiteResult::handle() const { - return qVariantFromValue(d->stmt); + return QVariant::fromValue(d->stmt); } ///////////////////////////////////////////////////////// @@ -697,7 +697,7 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const QVariant QSQLiteDriver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index ea476e5..89f3ed3 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -342,7 +342,7 @@ QSqlRecord QSQLite2Result::record() const QVariant QSQLite2Result::handle() const { - return qVariantFromValue(d->currentMachine); + return QVariant::fromValue(d->currentMachine); } ///////////////////////////////////////////////////////// @@ -558,7 +558,7 @@ QSqlRecord QSQLite2Driver::record(const QString &tbl) const QVariant QSQLite2Driver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLite2Driver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 2ab37de..1cf5fde 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -166,7 +166,7 @@ public: static QSqlDatabase database(const QString& name, bool open); static void addDatabase(const QSqlDatabase &db, const QString & name); static void removeDatabase(const QString& name); - static void invalidateDb(const QSqlDatabase &db, const QString &name); + static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn = true); static DriverDict &driverDict(); static void cleanConnections(); }; @@ -200,7 +200,7 @@ void QSqlDatabasePrivate::cleanConnections() QConnectionDict::iterator it = dict->begin(); while (it != dict->end()) { - invalidateDb(it.value(), it.key()); + invalidateDb(it.value(), it.key(), false); ++it; } dict->clear(); @@ -232,9 +232,9 @@ QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null() return &n; } -void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name) +void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn) { - if (db.d->ref != 1) { + if (db.d->ref != 1 && doWarn) { qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, " "all queries will cease to work.", name.toLocal8Bit().constData()); db.d->disable(); diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index c84f327..a996e88 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -95,6 +95,8 @@ public: virtual void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0) = 0; + virtual void registerRandomSeed(unsigned int seed) = 0; + static void outputString(const char *msg); static bool isTtyOutput(); }; diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index 1a0e737..59248a9 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -384,6 +384,7 @@ namespace QTest { } QPlainTestLogger::QPlainTestLogger() +: randomSeed(9), hasRandomSeed(false) { #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) InitializeCriticalSection(&QTest::outputCriticalSection); @@ -415,10 +416,17 @@ void QPlainTestLogger::startLogging() QTest::qt_snprintf(buf, sizeof(buf), "Testing %s\n", QTestResult::currentTestObjectName()); } else { - QTest::qt_snprintf(buf, sizeof(buf), - "********* Start testing of %s *********\n" - "Config: Using QTest library " QTEST_VERSION_STR - ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + if (hasRandomSeed) { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s, Random seed %d\n", QTestResult::currentTestObjectName(), qVersion(), randomSeed); + } else { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + } } QTest::outputMessage(buf); } @@ -480,4 +488,10 @@ void QPlainTestLogger::addMessage(MessageTypes type, const char *message, QTest::printMessage(QTest::messageType2String(type), message, file, line); } +void QPlainTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qplaintestlogger_p.h b/src/testlib/qplaintestlogger_p.h index f1f1d4e..9195600 100644 --- a/src/testlib/qplaintestlogger_p.h +++ b/src/testlib/qplaintestlogger_p.h @@ -75,6 +75,10 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); +private: + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 633d635..aa9b2bd 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -159,7 +159,7 @@ template<> inline char *toString(const QVariant &v) if (!v.isNull()) { vstring.append(','); if (v.canConvert(QVariant::String)) { - vstring.append(qVariantValue<QString>(v).toLatin1()); + vstring.append(qvariant_cast<QString>(v).toLatin1()); } else { vstring.append("<value not representable as string>"); diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h index a78113a..4dd0cb7 100644 --- a/src/testlib/qtest_global.h +++ b/src/testlib/qtest_global.h @@ -62,7 +62,7 @@ QT_MODULE(Test) # endif #endif -#if (defined (Q_CC_MSVC) && _MSC_VER < 1310) || defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) +#if defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) # define QTEST_NO_SPECIALIZATIONS #endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 17f1a6b..5934850 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -826,25 +826,46 @@ namespace QTest { static QObject *currentTestObject = 0; - static struct TestFunction { - TestFunction():function(0), data(0) {} - ~TestFunction() { delete [] data; } - int function; - char *data; - } *testFuncs; - + class TestFunction { + public: + TestFunction() : function_(-1), data_(0) {} + void set(int function, char *data) { function_ = function; data_ = data; } + char *data() const { return data_; } + int function() const { return function_; } + ~TestFunction() { delete[] data_; } + private: + int function_; + char *data_; + }; /** - * Contains the count of test functions that was supplied - * on the command line, if any. Hence, if lastTestFuncIdx is - * more than zero, those functions should be run instead of + * Contains the list of test functions that was supplied + * on the command line, if any. Hence, if not empty, + * those functions should be run instead of * all appearing in the test case. */ - static int lastTestFuncIdx = -1; + static TestFunction * testFuncs = 0; + static int testFuncCount = 0; + + /** Don't leak testFuncs on exit even on error */ + static struct TestFuncCleanup + { + void cleanup() + { + delete[] testFuncs; + testFuncCount = 0; + testFuncs = 0; + } + + ~TestFuncCleanup() { cleanup(); } + } testFuncCleaner; static int keyDelay = -1; static int mouseDelay = -1; static int eventDelay = -1; + static bool randomOrder = false; static int keyVerbose = -1; + static unsigned int seed = 0; + static bool seedSet = false; #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) static bool noCrashHandler = false; #endif @@ -930,6 +951,41 @@ int Q_TESTLIB_EXPORT defaultKeyDelay() return keyDelay; } +void seedRandom() +{ + static bool randomSeeded = false; + if (!randomSeeded) { + if (!QTest::seedSet) { + QTest::seed = QDateTime::currentDateTime().toTime_t(); + } + qsrand(QTest::seed); + randomSeeded = true; + } +} + +int qTestRandomSeed() +{ + Q_ASSERT(QTest::seedSet); + return QTest::seed; +} + +template<typename T> +void swap(T * array, int pos, int otherPos) +{ + T tmp = array[pos]; + array[pos] = array[otherPos]; + array[otherPos] = tmp; +} + +template<typename T> +static void randomizeList(T * array, int size) +{ + for (int i = 0; i != size; i++) { + int pos = qrand() % size; + swap(array, pos, i); + } +} + static bool isValidSlot(const QMetaMethod &sl) { if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty() @@ -971,8 +1027,6 @@ static int qToInt(char *str) static void qParseArgs(int argc, char *argv[]) { - lastTestFuncIdx = -1; - const char *testOptions = " options:\n" " -functions : Returns a list of current testfunctions\n" @@ -985,6 +1039,9 @@ static void qParseArgs(int argc, char *argv[]) " -v1 : Print enter messages for each testfunction\n" " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n" " -vs : Print every signal emitted\n" + " -random : Run testcases within each test in random order\n" + " -seed n : Positive integer to be used as seed for -random. If not specified,\n" + " the current time will be used as seed.\n" " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n" " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n" " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n" @@ -1100,6 +1157,22 @@ static void qParseArgs(int argc, char *argv[]) #endif } else if (strcmp(argv[i], "-eventcounter") == 0) { QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter); + } else if (strcmp(argv[i], "-random") == 0) { + QTest::randomOrder = true; + } else if (strcmp(argv[i], "-seed") == 0) { + bool argumentOk = false; + if (i + 1 < argc) { + char * endpt = 0; + long longSeed = strtol(argv[++i], &endpt, 10); + argumentOk = (*endpt == '\0' && longSeed >= 0); + QTest::seed = longSeed; + } + if (!argumentOk) { + printf("-seed needs an extra positive integer parameter to specify the seed\n"); + exit(1); + } else { + QTest::seedSet = true; + } } else if (strcmp(argv[i], "-minimumvalue") == 0) { if (i + 1 >= argc) { printf("-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n"); @@ -1140,6 +1213,10 @@ static void qParseArgs(int argc, char *argv[]) printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); } else { + if (!QTest::testFuncs) { + QTest::testFuncs = new QTest::TestFunction[512]; + } + int colon = -1; char buf[512], *data=0; int off; @@ -1161,17 +1238,16 @@ static void qParseArgs(int argc, char *argv[]) qPrintTestSlots(); exit(1); } - ++QTest::lastTestFuncIdx; - if (!QTest::testFuncs) { - struct Cleanup { ~Cleanup() { delete[] QTest::testFuncs; } }; - static Cleanup cleanup; - QTest::testFuncs = new TestFunction[512]; - } - QTest::testFuncs[QTest::lastTestFuncIdx].function = idx; - QTest::testFuncs[QTest::lastTestFuncIdx].data = data; - QTEST_ASSERT(QTest::lastTestFuncIdx < 512); + testFuncs[testFuncCount].set(idx, data); + testFuncCount++; + QTEST_ASSERT(QTest::testFuncCount < 512); } } + + if (QTest::seedSet && !QTest::randomOrder) { + printf("-seed requires -random\n"); + exit(1); + } } QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) @@ -1466,9 +1542,11 @@ static void qInvokeTestMethods(QObject *testObject) { const QMetaObject *metaObject = testObject->metaObject(); QTEST_ASSERT(metaObject); - - QTestLog::startLogging(); - + if (QTest::randomOrder) { + QTestLog::startLogging(QTest::seed); + } else { + QTestLog::startLogging(); + } QTestResult::setCurrentTestFunction("initTestCase"); QTestResult::setCurrentTestLocation(QTestResult::DataFunc); QTestTable::globalTestTable(); @@ -1484,21 +1562,31 @@ static void qInvokeTestMethods(QObject *testObject) if(!QTestResult::skipCurrentTest() && !previousFailed) { - if (lastTestFuncIdx >= 0) { - for (int i = 0; i <= lastTestFuncIdx; ++i) { - if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), - testFuncs[i].data)) + if (QTest::testFuncs) { + if (QTest::randomOrder) + randomizeList(QTest::testFuncs, QTest::testFuncCount); + for (int i = 0; i != QTest::testFuncCount; i++) { + if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(), + QTest::testFuncs[i].data())) { break; + } } + testFuncCleaner.cleanup(); } else { int methodCount = metaObject->methodCount(); - for (int i = 0; i < methodCount; ++i) { - QMetaMethod slotMethod = metaObject->method(i); - if (!isValidSlot(slotMethod)) + QMetaMethod *testMethods = new QMetaMethod[methodCount]; + for (int i = 0; i != methodCount; i++) + testMethods[i] = metaObject->method(i); + if (QTest::randomOrder) + randomizeList(testMethods, methodCount); + for (int i = 0; i != methodCount; i++) { + if (!isValidSlot(testMethods[i])) continue; - if (!qInvokeTestMethod(slotMethod.signature())) + if (!qInvokeTestMethod(testMethods[i].signature())) break; } + delete[] testMethods; + testMethods = 0; } } @@ -1689,6 +1777,9 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QTestResult::setCurrentTestObject(metaObject->className()); qParseArgs(argc, argv); + if (QTest::randomOrder) { + seedRandom(); + } #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { const QStringList origAppArgs(QCoreApplication::arguments()); diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp index 0ac9ea8..cc5397a 100644 --- a/src/testlib/qtestlightxmlstreamer.cpp +++ b/src/testlib/qtestlightxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestlightxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -164,8 +165,13 @@ void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, void QTestLightXmlStreamer::output(QTestElement *element) const { QTestCharBuffer buf; - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 398dec5..d58e231 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -168,6 +168,29 @@ namespace QTest { } } +void initLogger() +{ + switch (QTest::logMode) { + case QTestLog::Plain: + QTest::testLogger = new QPlainTestLogger; + break; + case QTestLog::XML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); + break; + }case QTestLog::LightXML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); + break; + }case QTestLog::XunitXML: + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); + } +} + } QTestLog::QTestLog() @@ -268,32 +291,20 @@ void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) QTest::testLogger->addBenchmarkResult(result); } -void QTestLog::startLogging() +void QTestLog::startLogging(unsigned int randomSeed) { QTEST_ASSERT(!QTest::testLogger); - - switch (QTest::logMode) { - case QTestLog::Plain: - QTest::testLogger = new QPlainTestLogger; - break; - case QTestLog::XML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); - break; - }case QTestLog::LightXML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); - break; - }case QTestLog::XunitXML: - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); - } - + QTest::initLogger(); + QTest::testLogger->registerRandomSeed(randomSeed); QTest::testLogger->startLogging(); + QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); +} +void QTestLog::startLogging() +{ + QTEST_ASSERT(!QTest::testLogger); + QTest::initLogger(); + QTest::testLogger->startLogging(); QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); } diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index d36ff04..01d39eb 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -83,6 +83,7 @@ public: static void info(const char *msg, const char *file, int line); static void startLogging(); + static void startLogging(unsigned int randomSeed); static void stopLogging(); static void setLogMode(LogMode mode); @@ -97,7 +98,6 @@ public: static void setMaxWarnings(int max); static void setFlushMode(FlushMode mode); - private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp index f0be6be..cab97d1 100644 --- a/src/testlib/qtestlogger.cpp +++ b/src/testlib/qtestlogger.cpp @@ -62,7 +62,8 @@ QTestLogger::QTestLogger(int fm) warningCounter(0), skipCounter(0), systemCounter(0), qdebugCounter(0), qwarnCounter(0), qfatalCounter(0), - infoCounter(0) + infoCounter(0), randomSeed_(0), + hasRandomSeed_(false) { } @@ -133,6 +134,14 @@ void QTestLogger::stopLogging() property->addAttribute(QTest::AI_PropertyValue, qVersion()); properties->addLogElement(property); + if (hasRandomSeed()) { + property = new QTestElement(QTest::LET_Property); + property->addAttribute(QTest::AI_Name, "RandomSeed"); + QTest::qt_snprintf(buf, sizeof(buf), "%i", randomSeed()); + property->addAttribute(QTest::AI_PropertyValue, buf); + properties->addLogElement(property); + } + currentLogElement->addLogElement(properties); currentLogElement->addLogElement(iterator); @@ -420,5 +429,21 @@ int QTestLogger::infoCount() const return infoCounter; } +void QTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed_ = seed; + hasRandomSeed_ = true; +} + +unsigned int QTestLogger::randomSeed() const +{ + return randomSeed_; +} + +bool QTestLogger::hasRandomSeed() const +{ + return hasRandomSeed_; +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h index bb7a358..8932a85 100644 --- a/src/testlib/qtestlogger_p.h +++ b/src/testlib/qtestlogger_p.h @@ -101,6 +101,9 @@ class QTestLogger : public QAbstractTestLogger int qwarnCount() const; int qfatalCount() const; int infoCount() const; + void registerRandomSeed(unsigned int seed); + unsigned int randomSeed() const; + bool hasRandomSeed() const; private: QTestElement *listOfTestcases; @@ -121,6 +124,8 @@ class QTestLogger : public QAbstractTestLogger int qwarnCounter; int qfatalCounter; int infoCounter; + unsigned int randomSeed_; + bool hasRandomSeed_; }; QT_END_NAMESPACE diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index 8c52a82..bbe3e7f 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -191,10 +191,13 @@ bool QTestResult::expectFail(const char *dataIndex, const char *comment, QTEST_ASSERT(comment); QTEST_ASSERT(mode > 0); - if (!isExpectFailData(dataIndex)) + if (!isExpectFailData(dataIndex)) { + delete[] comment; return true; // we don't care + } if (QTest::expectFailMode) { + delete[] comment; clearExpectFail(); addFailure("Already expecting a fail", file, line); return false; diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp index f63c221..a6b8376 100644 --- a/src/testlib/qtestxmlstreamer.cpp +++ b/src/testlib/qtestxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -204,8 +205,13 @@ void QTestXmlStreamer::output(QTestElement *element) const quotedTc.constData()); outputString(buf.constData()); - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", - qVersion(), QTEST_VERSION_STR ); + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index 07e8ef0..2bf7d77 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -93,7 +93,7 @@ namespace QTest { QXmlTestLogger::QXmlTestLogger(XmlMode mode ) - :xmlmode(mode) + :xmlmode(mode), randomSeed(0), hasRandomSeed(false) { } @@ -116,11 +116,20 @@ void QXmlTestLogger::startLogging() outputString(buf.constData()); } - QTest::qt_asprintf(&buf, - "<Environment>\n" - " <QtVersion>%s</QtVersion>\n" - " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" - "</Environment>\n", qVersion()); + if (hasRandomSeed) { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + " <RandomSeed>%d</RandomSeed>\n" + "</Environment>\n", qVersion(), randomSeed); + } else { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + "</Environment>\n", qVersion()); + } outputString(buf.constData()); } @@ -441,4 +450,10 @@ int QXmlTestLogger::xmlCdata(QTestCharBuffer* str, char const* src) return allocateStringFn(str, src, QXmlTestLogger::xmlCdata); } +void QXmlTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index ae918dc..82dd8a6 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -79,6 +79,8 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); + static int xmlCdata(QTestCharBuffer *dest, char const* src); static int xmlQuote(QTestCharBuffer *dest, char const* src); static int xmlCdata(QTestCharBuffer *dest, char const* src, size_t n); @@ -86,6 +88,8 @@ public: private: XmlMode xmlmode; + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/tools/uic3/converter.cpp b/src/tools/uic3/converter.cpp index 2ee939d..8fac4d1 100644 --- a/src/tools/uic3/converter.cpp +++ b/src/tools/uic3/converter.cpp @@ -864,7 +864,7 @@ DomLayoutItem *Ui3Reader::createLayoutItem(const QDomElement &e) Variant var; var.createSize(0, 0); - QVariant def = qVariantFromValue(var); + QVariant def = QVariant::fromValue(var); Size size = asVariant(DomTool::readProperty(e, QLatin1String("sizeHint"), def)).size; QString sizeType = QLatin1String("QSizePolicy::") + DomTool::readProperty(e, QLatin1String("sizeType"), QLatin1String("Expanding")).toString(); diff --git a/src/tools/uic3/domtool.cpp b/src/tools/uic3/domtool.cpp index 526b41c..cefbbb4 100644 --- a/src/tools/uic3/domtool.cpp +++ b/src/tools/uic3/domtool.cpp @@ -169,7 +169,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createRect(x, y, w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("point")) { QDomElement n3 = e.firstChild().toElement(); int x = 0, y = 0; @@ -181,7 +181,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createPoint(x,y); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("size")) { QDomElement n3 = e.firstChild().toElement(); int w = 0, h = 0; @@ -193,10 +193,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createSize(w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("color")) { var.color = readColor(e); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("font")) { QDomElement n3 = e.firstChild().toElement(); Font f; @@ -217,7 +217,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.font = f; - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("string")) { v = QVariant(e.firstChild().toText().data()); QDomElement n = e; @@ -258,10 +258,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu var.sizePolicy.verstretch = n3.firstChild().toText().data().toInt(); n3 = n3.nextSibling().toElement(); } - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("cursor")) { var.createCursor(e.firstChild().toText().data().toInt()); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("stringlist")) { QStringList lst; QDomElement n; diff --git a/src/tools/uic3/domtool.h b/src/tools/uic3/domtool.h index ad597a1..8fe0793 100644 --- a/src/tools/uic3/domtool.h +++ b/src/tools/uic3/domtool.h @@ -266,7 +266,7 @@ QT_BEGIN_NAMESPACE inline Variant asVariant(const QVariant &v) { Variant var; - var = qVariantValue<Variant>(v); + var = qvariant_cast<Variant>(v); return var; } diff --git a/src/xmlpatterns/api/quriloader.cpp b/src/xmlpatterns/api/quriloader.cpp index e0a7542..c653661 100644 --- a/src/xmlpatterns/api/quriloader.cpp +++ b/src/xmlpatterns/api/quriloader.cpp @@ -69,7 +69,7 @@ QNetworkReply *URILoader::createRequest(Operation op, const QNetworkRequest &req const QVariant variant(m_variableLoader->valueFor(m_namePool->allocateQName(QString(), name, QString()))); if(!variant.isNull() && variant.userType() == qMetaTypeId<QIODevice *>()) - return new QIODeviceDelegate(qVariantValue<QIODevice *>(variant)); + return new QIODeviceDelegate(qvariant_cast<QIODevice *>(variant)); else { /* If we're entering this code path, the variable URI identified a variable diff --git a/src/xmlpatterns/api/qvariableloader.cpp b/src/xmlpatterns/api/qvariableloader.cpp index 612fa67..648fda4 100644 --- a/src/xmlpatterns/api/qvariableloader.cpp +++ b/src/xmlpatterns/api/qvariableloader.cpp @@ -131,12 +131,12 @@ SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name, return CommonSequenceTypes::ExactlyOneAnyURI; else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->staticType(); } else { - return makeGenericSequenceType(AtomicValue::qtToXDMType(qVariantValue<QXmlItem>(variant)), + return makeGenericSequenceType(AtomicValue::qtToXDMType(qvariant_cast<QXmlItem>(variant)), Cardinality::exactlyOne()); } } @@ -154,12 +154,12 @@ Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name, return makeSingletonIterator(itemForName(name)); else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context))); } - const QVariant v(qVariantValue<QXmlItem>(variant).toAtomicValue()); + const QVariant v(qvariant_cast<QXmlItem>(variant).toAtomicValue()); switch(v.type()) { @@ -179,7 +179,7 @@ Item VariableLoader::itemForName(const QXmlName &name) const if(variant.userType() == qMetaTypeId<QIODevice *>()) return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName()))); - const QXmlItem item(qVariantValue<QXmlItem>(variant)); + const QXmlItem item(qvariant_cast<QXmlItem>(variant)); if(item.isNode()) return Item::fromPublic(item); @@ -210,8 +210,8 @@ bool VariableLoader::isSameType(const QVariant &v1, return true; /* Ok, we have two QXmlItems. */ - const QXmlItem i1(qVariantValue<QXmlItem>(v1)); - const QXmlItem i2(qVariantValue<QXmlItem>(v2)); + const QXmlItem i1(qvariant_cast<QXmlItem>(v1)); + const QXmlItem i2(qvariant_cast<QXmlItem>(v2)); if(i1.isNode()) { diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 55af49b..4d6a3b6 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -534,7 +534,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value) } const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(value)); + const QVariant variant(QVariant::fromValue(value)); /* If the type of the variable changed(as opposed to only the value), * we will have to recompile. */ @@ -610,7 +610,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device) if(device) { - const QVariant variant(qVariantFromValue(device)); + const QVariant variant(QVariant::fromValue(device)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); @@ -1184,7 +1184,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlQuery &query) Q_ASSERT_X(query.isValid(), Q_FUNC_INFO, "The query being bound must be valid."); const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(query)); + const QVariant variant(QVariant::fromValue(query)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); diff --git a/src/xmlpatterns/data/qatomicvalue.cpp b/src/xmlpatterns/data/qatomicvalue.cpp index c4f3578..5bb9a4f 100644 --- a/src/xmlpatterns/data/qatomicvalue.cpp +++ b/src/xmlpatterns/data/qatomicvalue.cpp @@ -121,7 +121,7 @@ QVariant AtomicValue::toQt(const AtomicValue *const value) || BuiltinTypes::xsHexBinary->xdtTypeMatches(t)) return QVariant(value->as<Base64Binary>()->asByteArray()); else if(BuiltinTypes::xsQName->xdtTypeMatches(t)) - return qVariantFromValue(value->as<QNameValue>()->qName()); + return QVariant::fromValue(value->as<QNameValue>()->qName()); else { /* A type we don't support in Qt. Includes xs:time currently. */ diff --git a/src/xmlpatterns/utils/qautoptr_p.h b/src/xmlpatterns/utils/qautoptr_p.h index 060e7be..173999f 100644 --- a/src/xmlpatterns/utils/qautoptr_p.h +++ b/src/xmlpatterns/utils/qautoptr_p.h @@ -122,7 +122,6 @@ namespace QPatternist return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename L> operator AutoPtrRef<L>() { @@ -139,7 +138,6 @@ namespace QPatternist inline AutoPtr(AutoPtr<L>& other) : m_ptr(other.release()) { } -#endif inline T *release() { |