diff options
author | Warwick Allison <warwick.allison@nokia.com> | 2010-02-01 01:41:07 (GMT) |
---|---|---|
committer | Warwick Allison <warwick.allison@nokia.com> | 2010-02-01 01:41:07 (GMT) |
commit | 7e85c6dc7ba0aaa6dfcad40dc0e9df0e2adb3741 (patch) | |
tree | 07e839b8dd88c381471b96917ef5aafa484233b1 /src | |
parent | 6e8feab83fa9303b1345f4a27478ba3ee0316e86 (diff) | |
parent | 5cf8677758e6fbfa5bf360c73519c14630db808c (diff) | |
download | Qt-7e85c6dc7ba0aaa6dfcad40dc0e9df0e2adb3741.zip Qt-7e85c6dc7ba0aaa6dfcad40dc0e9df0e2adb3741.tar.gz Qt-7e85c6dc7ba0aaa6dfcad40dc0e9df0e2adb3741.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Conflicts:
src/declarative/util/qmlpixmapcache.cpp
Diffstat (limited to 'src')
239 files changed, 7409 insertions, 5147 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index 9878472..436e8e4 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -23,7 +23,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <AudioEffectBase.h> -#include <Phonon/EffectInterface> +#include <phonon/effectinterface.h> #include "audioplayer.h" #include "effectparameter.h" diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index dbcbe63..cec5568 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -19,8 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef PHONON_MMF_ABSTRACTPLAYER_H #define PHONON_MMF_ABSTRACTPLAYER_H -#include <Phonon/phononnamespace.h> -#include <Phonon/MediaSource.h> +#include <phonon/phononnamespace.h> +#include <phonon/mediasource.h> #include <QObject> diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h index 6b85625..9361544 100644 --- a/src/3rdparty/phonon/mmf/backend.h +++ b/src/3rdparty/phonon/mmf/backend.h @@ -22,8 +22,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "ancestormovemonitor.h" #include "effectfactory.h" -#include <Phonon/MediaSource> -#include <Phonon/BackendInterface> +#include <phonon/mediasource.h> +#include <phonon/backendinterface.h> #include <QScopedPointer> QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/effectparameter.h b/src/3rdparty/phonon/mmf/effectparameter.h index 27cc018..892ed4d 100644 --- a/src/3rdparty/phonon/mmf/effectparameter.h +++ b/src/3rdparty/phonon/mmf/effectparameter.h @@ -19,7 +19,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef PHONON_MMF_EFFECTPARAMETER_H #define PHONON_MMF_EFFECTPARAMETER_H -#include <Phonon/EffectParameter> +#include <phonon/effectparameter.h> QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index c87d755..d6248e2 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -19,8 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef PHONON_MMF_MEDIAOBJECT_H #define PHONON_MMF_MEDIAOBJECT_H -#include <Phonon/MediaSource> -#include <Phonon/MediaObjectInterface> +#include <phonon/mediasource.h> +#include <phonon/mediaobjectinterface.h> #include <QScopedPointer> #include <QTimer> diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.h b/src/3rdparty/phonon/mmf/mmf_medianode.h index 0ed21c4..f2f64e0 100644 --- a/src/3rdparty/phonon/mmf/mmf_medianode.h +++ b/src/3rdparty/phonon/mmf/mmf_medianode.h @@ -20,7 +20,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #define PHONON_MMF_MEDIANODE_H #include <QObject> -#include <Phonon/EffectInterface> +#include <phonon/effectinterface.h> #include "audioplayer.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h index 2788401..3e9c036 100644 --- a/src/3rdparty/phonon/mmf/videooutput.h +++ b/src/3rdparty/phonon/mmf/videooutput.h @@ -24,7 +24,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QRect> #include "defs.h" -#include <Phonon/VideoWidget> +#include <phonon/videowidget.h> #include <e32std.h> class RWindowBase; diff --git a/src/3rdparty/phonon/mmf/videowidget.h b/src/3rdparty/phonon/mmf/videowidget.h index a876748..899dca6 100644 --- a/src/3rdparty/phonon/mmf/videowidget.h +++ b/src/3rdparty/phonon/mmf/videowidget.h @@ -23,8 +23,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "videooutput.h" #include <QtGui/QWidget> -#include <Phonon/VideoWidget> -#include <Phonon/VideoWidgetInterface> +#include <phonon/videowidget.h> +#include <phonon/videowidgetinterface.h> QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/webkit/JavaScriptCore/ChangeLog b/src/3rdparty/webkit/JavaScriptCore/ChangeLog index e292418..b943840 100644 --- a/src/3rdparty/webkit/JavaScriptCore/ChangeLog +++ b/src/3rdparty/webkit/JavaScriptCore/ChangeLog @@ -10,17 +10,6 @@ (OpaqueJSClass::OpaqueJSClass): (OpaqueJSClassContextData::OpaqueJSClassContextData): -2010-01-07 Norbert Leser <norbert.leser@nokia.com> - - Reviewed by NOBODY (OOPS!). - - Added time-based optimization and increased optimization level to O3, - conditionally for COMPILER(RVCT), - for increasing performance of JavaScript execution. - (Default settings are Ospace and O2) - - * runtime/Structure.h: - 2009-11-19 Thiago Macieira <thiago.macieira@nokia.com> Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h index ecdd997..f355c53 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h @@ -45,12 +45,6 @@ #define DUMP_PROPERTYMAP_STATS 0 #endif -#if COMPILER(RVCT) -#pragma arm -#pragma Otime -#pragma O3 -#endif - namespace JSC { class MarkStack; diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index bc6d661..6fe71d6 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - 8b9165d3bc84d1c8cc7df49a191cc3857b5530d4 + 8f5ca3ba5da63a47d4f90bbd867d3e8453443dd3 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index 02daf86..8e1c965 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,48 @@ +2010-01-17 Srinidhi Shreedhara <srinidhi.shreedhara@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] [Symbian] SetWindow call in npapi plugin does not happen when the cooridnates are negative + https://bugs.webkit.org/show_bug.cgi?id=33573 + + * plugins/symbian/PluginViewSymbian.cpp: + (WebCore::PluginView::setNPWindowIfNeeded): Remove tests for negative + coordinates for early return. + +2010-01-14 Norbert Leser <norbert.leser@nokia.com> + + Reviewed by Laszlo Gombos. + + Platform Symbian specific: + Added time-based optimization (-Otime) and increased optimization level to -O3, + conditionally for RVCT compiler (for ARM), for increasing performance + (primarily affecting JavaScript execution). + Default settings are -Ospace and -O2. + + No new tests needed because no new funtionality is introduced, + only potential regression on existing tests needs to be evaluated. + + * WebCore.pro: + +2010-01-13 Girish Ramakrishnan <girish@forwardbias.in> + + Reviewed by Simon Hausmann. + + [Qt/Win] Flash in QGraphicsWebView does not process hover correctly. + + https://bugs.webkit.org/show_bug.cgi?id=33591 + + Mouse hover does not work as expected with the flash in some sites. + - http://www.bbc.co.uk/ Hover over the map + - http://www.barbie.com/ Hover over the menu items (Games, Videos) + The problem appears to be that Flash queries NPNVnetscapeWindow on every + mouse hover. I do not how flash uses this value but returning 0 when flash + is in windowless mode solves the problem (When using QGraphicsWebView we + inject wmode opaque, thereby putting the plugin in windowless mode). + + * plugins/win/PluginViewWin.cpp: + (windowHandleForPageClient): + 2010-01-13 Miikka Heikkinen <miikka.heikkinen@digia.com> Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 9432217..04aba62 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -24,6 +24,8 @@ symbian: { # RO text (code) section in qtwebkit.dll exceeds allocated space for gcce udeb target. # Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000. MMP_RULES += "LINKEROPTION armcc --rw-base 0xE00000" + MMP_RULES += ALWAYS_BUILD_AS_ARM + QMAKE_CXXFLAGS.ARMCC += -OTime -O3 } include($$PWD/../WebKit.pri) diff --git a/src/3rdparty/webkit/WebCore/platform/PopupMenu.h b/src/3rdparty/webkit/WebCore/platform/PopupMenu.h index 2315f02..f2fffb5 100644 --- a/src/3rdparty/webkit/WebCore/platform/PopupMenu.h +++ b/src/3rdparty/webkit/WebCore/platform/PopupMenu.h @@ -44,6 +44,7 @@ typedef struct HBITMAP__* HBITMAP; namespace WebCore { class QWebPopup; } +class QGraphicsProxyWidget; #elif PLATFORM(GTK) typedef struct _GtkMenu GtkMenu; typedef struct _GtkMenuItem GtkMenuItem; @@ -147,6 +148,7 @@ private: void clear(); void populate(const IntRect&); QWebPopup* m_popup; + QGraphicsProxyWidget* m_proxy; #elif PLATFORM(WIN) // ScrollBarClient virtual void valueChanged(Scrollbar*); diff --git a/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp index f6ec4f7..989b34c 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp @@ -1,6 +1,7 @@ /* * This file is part of the popup menu implementation for <select> elements in WebCore. * + * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com @@ -35,6 +36,9 @@ #include <QAction> #include <QDebug> +#include <QGraphicsProxyWidget> +#include <QGraphicsScene> +#include <QGraphicsView> #include <QListWidget> #include <QListWidgetItem> #include <QMenu> @@ -46,6 +50,7 @@ namespace WebCore { PopupMenu::PopupMenu(PopupMenuClient* client) : m_popupClient(client) + , m_proxy(0) { m_popup = new QWebPopup(client); } @@ -53,6 +58,7 @@ PopupMenu::PopupMenu(PopupMenuClient* client) PopupMenu::~PopupMenu() { delete m_popup; + delete m_proxy; } void PopupMenu::clear() @@ -92,8 +98,19 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) rect.moveTopLeft(v->contentsToWindow(r.topLeft())); rect.setHeight(m_popup->sizeHint().height()); - m_popup->setParent(client->ownerWidget()); - m_popup->setGeometry(rect); + if (QGraphicsView* view = qobject_cast<QGraphicsView*>(client->ownerWidget())) { + if (!m_proxy) { + m_proxy = new QGraphicsProxyWidget; + m_proxy->setWidget(m_popup); + view->scene()->addItem(m_proxy); + } else + m_proxy->setVisible(true); + m_proxy->setGeometry(rect); + } else { + m_popup->setParent(client->ownerWidget()); + m_popup->setGeometry(rect); + } + m_popup->setCurrentIndex(index); m_popup->exec(); } diff --git a/src/3rdparty/webkit/WebCore/platform/qt/QWebPopup.cpp b/src/3rdparty/webkit/WebCore/platform/qt/QWebPopup.cpp index d077079..f7ebbc7 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/QWebPopup.cpp +++ b/src/3rdparty/webkit/WebCore/platform/qt/QWebPopup.cpp @@ -26,6 +26,7 @@ #include <QApplication> #include <QInputContext> #include <QMouseEvent> +#include <QGraphicsProxyWidget> namespace WebCore { @@ -67,6 +68,10 @@ void QWebPopup::hidePopup() } QComboBox::hidePopup(); + + if (QGraphicsProxyWidget* proxy = graphicsProxyWidget()) + proxy->setVisible(false); + if (!m_popupVisible) return; diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp index 14e25b1..cf69723 100644 --- a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp @@ -280,8 +280,6 @@ void PluginView::setNPWindowIfNeeded() m_npWindow.width = m_windowRect.width(); m_npWindow.height = m_windowRect.height(); - if (m_npWindow.x < 0 || m_npWindow.y < 0 || m_npWindow.width <= 0 || m_npWindow.height <= 0) - return; PluginView::setCurrentPluginView(this); JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); diff --git a/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp b/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp index b313afb..ab71273 100644 --- a/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp @@ -86,7 +86,9 @@ static inline HWND windowHandleForPageClient(PlatformPageClient client) #if PLATFORM(QT) if (!client) return 0; - return client->ownerWidget()->winId(); + if (QWidget* pluginParent = qobject_cast<QWidget*>(client->pluginParent())) + return pluginParent->winId(); + return 0; #else return client; #endif diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 6d08c32..a289ec0 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -1708,8 +1708,14 @@ QWebPage::~QWebPage() FrameLoader *loader = d->mainFrame->d->frame->loader(); if (loader) loader->detachFromParent(); - if (d->inspector) - d->inspector->setPage(0); + if (d->inspector) { + // Since we have to delete an internal inspector, + // call setInspector(0) directly to prevent potential crashes + if (d->inspectorIsInternalOnly) + d->setInspector(0); + else + d->inspector->setPage(0); + } delete d; } diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 357b787..ee555f3 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,22 @@ +2009-11-19 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix QWebInspector destruction problem. + https://bugs.webkit.org/show_bug.cgi?id=31664 + + * Api/qwebpage.cpp: + (QWebPage::~QWebPage): + +2010-01-14 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Update Symbian .def symbol export files after private API additions. + + * symbian/bwins/QtWebKitu.def: + * symbian/eabi/QtWebKitu.def: + 2009-12-18 Joe Ligman <joseph.ligman@nokia.com> Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def index e5631f8..086e986 100644 --- a/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def @@ -620,4 +620,8 @@ EXPORTS ?staticMetaObject@QWebPage@@2UQMetaObject@@B @ 619 NONAME ; struct QMetaObject const QWebPage::staticMetaObject ?staticMetaObject@QWebView@@2UQMetaObject@@B @ 620 NONAME ; struct QMetaObject const QWebView::staticMetaObject ?attributeNames@QWebElement@@QBE?AVQStringList@@ABVQString@@@Z @ 621 NONAME ; class QStringList QWebElement::attributeNames(class QString const &) const + ?qt_networkAccessAllowed@@YAX_N@Z @ 622 NONAME ; void qt_networkAccessAllowed(bool) + ?qt_resumeActiveDOMObjects@@YAXPAVQWebFrame@@@Z @ 623 NONAME ; void qt_resumeActiveDOMObjects(class QWebFrame *) + ?qt_suspendActiveDOMObjects@@YAXPAVQWebFrame@@@Z @ 624 NONAME ; void qt_suspendActiveDOMObjects(class QWebFrame *) + ?qtwebkit_webframe_scrollRecursively@@YA_NPAVQWebFrame@@HH@Z @ 625 NONAME ; bool qtwebkit_webframe_scrollRecursively(class QWebFrame *, int, int) diff --git a/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def index 4aad884..5dd2e20 100644 --- a/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def @@ -690,4 +690,8 @@ EXPORTS _ZThn8_N16QGraphicsWebView10itemChangeEN13QGraphicsItem18GraphicsItemChangeERK8QVariant @ 689 NONAME _ZThn8_NK16QGraphicsWebView16inputMethodQueryEN2Qt16InputMethodQueryE @ 690 NONAME _ZNK11QWebElement14attributeNamesERK7QString @ 691 NONAME + _Z23qt_networkAccessAllowedb @ 692 NONAME + _Z25qt_resumeActiveDOMObjectsP9QWebFrame @ 693 NONAME + _Z26qt_suspendActiveDOMObjectsP9QWebFrame @ 694 NONAME + _Z35qtwebkit_webframe_scrollRecursivelyP9QWebFrameii @ 695 NONAME diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 2b4ab47..cedb43f 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -299,8 +299,6 @@ void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation) return; if (QAbstractAnimationPrivate::get(animation)->isPause) { - if (animation->duration() == -1) - qDebug() << "toto"; runningPauseAnimations << animation; } else runningLeafAnimations++; diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index eec5b30..cfd7cc2 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -256,7 +256,8 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState, Q_D(QPropertyAnimation); if (!d->target && oldState == Stopped) { - qWarning("QPropertyAnimation::updateState: Changing state of an animation without target"); + qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without target", + d->propertyName.constData()); return; } @@ -279,10 +280,16 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState, if (oldState == Stopped) { d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData())); //let's check if we have a start value and an end value - if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) - qWarning("QPropertyAnimation::updateState: starting an animation without start value"); - if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) - qWarning("QPropertyAnimation::updateState: starting an animation without end value"); + if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) { + qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without start value", + d->propertyName.constData(), d->target.data()->metaObject()->className(), + qPrintable(d->target.data()->objectName())); + } + if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) { + qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without end value", + d->propertyName.constData(), d->target.data()->metaObject()->className(), + qPrintable(d->target.data()->objectName())); + } } } else if (hash.value(key) == this) { hash.remove(key); diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index e015863..8c824f3 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -205,7 +205,7 @@ inline bool QBasicAtomicInt::deref() template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) { - return (T *)_InterlockedExchangePointer(&_q_value, newValue); + return (T *)_InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), newValue); } template <typename T> diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 52e9845..abdafc3 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.6.1" +#define QT_VERSION_STR "4.6.2" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x040601 +#define QT_VERSION 0x040602 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -2419,6 +2419,10 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); //enabling new graphics resources #define QT_SYMBIAN_SUPPORTS_SGIMAGE #define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER + +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#define Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE +#endif #endif diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 6395cc7..728c316 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -643,13 +643,14 @@ QFile::remove() qWarning("QFile::remove: Empty or null file name"); return false; } + unsetError(); close(); if(error() == QFile::NoError) { if(fileEngine()->remove()) { unsetError(); return true; } - d->setError(QFile::RemoveError, fileEngine()->errorString()); + d->setError(QFile::RemoveError, d->fileEngine->errorString()); } return false; } @@ -703,7 +704,7 @@ QFile::rename(const QString &newName) if (fileEngine()->rename(newName)) { unsetError(); // engine was able to handle the new name so we just reset it - fileEngine()->setFileName(newName); + d->fileEngine->setFileName(newName); d->fileName = newName; return true; } @@ -739,7 +740,7 @@ QFile::rename(const QString &newName) if (error) { out.remove(); } else { - fileEngine()->setFileName(newName); + d->fileEngine->setFileName(newName); setPermissions(permissions()); unsetError(); setFileName(newName); @@ -804,7 +805,7 @@ QFile::link(const QString &linkName) unsetError(); return true; } - d->setError(QFile::RenameError, fileEngine()->errorString()); + d->setError(QFile::RenameError, d->fileEngine->errorString()); return false; } @@ -993,10 +994,10 @@ bool QFile::open(OpenMode mode) seek(size()); return true; } - QFile::FileError err = fileEngine()->error(); + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::OpenError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); return false; } @@ -1151,12 +1152,11 @@ bool QFile::open(int fd, OpenMode mode) int QFile::handle() const { - if (!isOpen()) + Q_D(const QFile); + if (!isOpen() || !d->fileEngine) return -1; - if (QAbstractFileEngine *engine = fileEngine()) - return engine->handle(); - return -1; + return d->fileEngine->handle(); } /*! @@ -1188,13 +1188,12 @@ QFile::handle() const uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags) { Q_D(QFile); - QAbstractFileEngine *engine = fileEngine(); - if (engine - && engine->supportsExtension(QAbstractFileEngine::MapExtension)) { + if (fileEngine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) { unsetError(); - uchar *address = engine->map(offset, size, flags); + uchar *address = d->fileEngine->map(offset, size, flags); if (address == 0) - d->setError(engine->error(), engine->errorString()); + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); return address; } return 0; @@ -1211,13 +1210,12 @@ uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags) bool QFile::unmap(uchar *address) { Q_D(QFile); - QAbstractFileEngine *engine = fileEngine(); - if (engine - && engine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { + if (fileEngine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { unsetError(); - bool success = engine->unmap(address); + bool success = d->fileEngine->unmap(address); if (!success) - d->setError(engine->error(), engine->errorString()); + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); return success; } return false; @@ -1250,13 +1248,14 @@ QFile::resize(qint64 sz) Q_D(QFile); if (!d->ensureFlushed()) return false; - if (isOpen() && fileEngine()->pos() > sz) + fileEngine(); + if (isOpen() && d->fileEngine->pos() > sz) seek(sz); - if(fileEngine()->setSize(sz)) { + if(d->fileEngine->setSize(sz)) { unsetError(); return true; } - d->setError(QFile::ResizeError, fileEngine()->errorString()); + d->setError(QFile::ResizeError, d->fileEngine->errorString()); return false; } @@ -1320,7 +1319,7 @@ QFile::setPermissions(Permissions permissions) unsetError(); return true; } - d->setError(QFile::PermissionsError, fileEngine()->errorString()); + d->setError(QFile::PermissionsError, d->fileEngine->errorString()); return false; } @@ -1353,23 +1352,27 @@ bool QFile::flush() { Q_D(QFile); + if (!d->fileEngine) { + qWarning("QFile::flush: No file engine. Is IODevice open?"); + return false; + } + if (!d->writeBuffer.isEmpty()) { qint64 size = d->writeBuffer.size(); - if (_qfile_writeData(d->fileEngine ? d->fileEngine : fileEngine(), - &d->writeBuffer) != size) { - QFile::FileError err = fileEngine()->error(); + if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) { + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::WriteError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); return false; } } - if (!fileEngine()->flush()) { - QFile::FileError err = fileEngine()->error(); + if (!d->fileEngine->flush()) { + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::WriteError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); return false; } return true; @@ -1394,10 +1397,10 @@ QFile::close() d->writeBuffer.clear(); // keep earlier error from flush - if (fileEngine()->close() && flushed) + if (d->fileEngine->close() && flushed) unsetError(); else if (flushed) - d->setError(fileEngine()->error(), fileEngine()->errorString()); + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); } /*! @@ -1450,10 +1453,10 @@ bool QFile::atEnd() const return false; // If the file engine knows best, say what it says. - if (fileEngine()->supportsExtension(QAbstractFileEngine::AtEndExtension)) { + if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) { // Check if the file engine supports AtEndExtension, and if it does, // check if the file engine claims to be at the end. - return fileEngine()->atEnd(); + return d->fileEngine->atEnd(); } // Fall back to checking how much is available (will stat files). @@ -1475,11 +1478,11 @@ bool QFile::seek(qint64 off) if (!d->ensureFlushed()) return false; - if (!fileEngine()->seek(off) || !QIODevice::seek(off)) { - QFile::FileError err = fileEngine()->error(); + if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) { + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::PositionError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); return false; } unsetError(); @@ -1495,8 +1498,8 @@ qint64 QFile::readLineData(char *data, qint64 maxlen) if (!d->ensureFlushed()) return -1; - if (fileEngine()->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) - return fileEngine()->readLine(data, maxlen); + if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) + return d->fileEngine->readLine(data, maxlen); // Fall back to QIODevice's readLine implementation if the engine // cannot do it faster. @@ -1514,18 +1517,14 @@ qint64 QFile::readData(char *data, qint64 len) if (!d->ensureFlushed()) return -1; - qint64 ret = -1; - qint64 read = fileEngine()->read(data, len); - if (read != -1) - ret = read; - - if(ret < 0) { - QFile::FileError err = fileEngine()->error(); + qint64 read = d->fileEngine->read(data, len); + if(read < 0) { + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::ReadError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); } - return ret; + return read; } /*! @@ -1605,13 +1604,12 @@ QFile::writeData(const char *data, qint64 len) // Write directly to the engine if the block size is larger than // the write buffer size. if (!buffered || len > QFILE_WRITEBUFFER_SIZE) { - QAbstractFileEngine *fe = d->fileEngine ? d->fileEngine : fileEngine(); - qint64 ret = fe->write(data, len); + qint64 ret = d->fileEngine->write(data, len); if(ret < 0) { - QFile::FileError err = fileEngine()->error(); + QFile::FileError err = d->fileEngine->error(); if(err == QFile::UnspecifiedError) err = QFile::WriteError; - d->setError(err, fileEngine()->errorString()); + d->setError(err, d->fileEngine->errorString()); } return ret; } diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 74e5f74..a131d6c 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -5932,7 +5932,7 @@ void QUrl::detach() */ bool QUrl::isDetached() const { - return d && d->ref == 1; + return !d || d->ref == 1; } diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 9dff06a..0aa534a 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -75,7 +75,6 @@ public: RemovePath = 0x20, RemoveQuery = 0x40, RemoveFragment = 0x80, - // 0x100: private: normalized StripTrailingSlash = 0x10000 }; diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 1b167e2..3f69b4f 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -107,13 +107,13 @@ QT_BEGIN_NAMESPACE \value ApplicationLayoutDirectionChange The default application layout direction has changed. \value ApplicationPaletteChange The default application palette has changed. \value ApplicationWindowIconChange The application's icon has changed. - \value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP). \value ChildAdded An object gets a child (QChildEvent). \value ChildInserted An object gets a child (QChildEvent). Qt3Support only, use ChildAdded instead. \value ChildPolished A widget child gets polished (QChildEvent). \value ChildRemoved An object loses a child (QChildEvent). \value Clipboard The clipboard contents have changed (QClipboardEvent). \value Close Widget was closed (QCloseEvent). + \value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP). \value ContentsRectChange The margins of the widget's content rect changed. \value ContextMenu Context popup menu (QContextMenuEvent). \value CursorChange The widget's cursor has changed. diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f09047e..5298fff 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2956,6 +2956,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, } /*!\internal + +Disconnect a single signal connection. If QMetaObject::connect() has been called +multiple times for the same sender, signal_index, receiver and method_index only +one of these connections will be removed. */ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, const QObject *receiver, int method_index) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index d2fbf5a..556093f 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -538,7 +538,7 @@ QByteArray qUncompress(const uchar* data, int nbytes) forever { ulong alloc = len; - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc)))); + d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + alloc)))); if (!d) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); @@ -551,7 +551,7 @@ 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.data(), sizeof(QByteArray::Data) + len)))); + d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + len)))); if (!d) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); @@ -561,6 +561,7 @@ QByteArray qUncompress(const uchar* data, int nbytes) d->ref = 1; d->alloc = d->size = len; d->data = d->array; + d->array[len] = 0; return QByteArray(d.take(), 0, 0); diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 0ef92d9..b6a2df4 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -125,7 +125,7 @@ \value OutCubic \inlineimage qeasingcurve-outcubic.png \br Easing curve for a cubic (t^3) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png \br Easing curve for a cubic (t^3) function: @@ -141,7 +141,7 @@ \value OutQuart \inlineimage qeasingcurve-outquart.png \br Easing curve for a cubic (t^4) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutQuart \inlineimage qeasingcurve-inoutquart.png \br Easing curve for a cubic (t^4) function: @@ -157,7 +157,7 @@ \value OutQuint \inlineimage qeasingcurve-outquint.png \br Easing curve for a cubic (t^5) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutQuint \inlineimage qeasingcurve-inoutquint.png \br Easing curve for a cubic (t^5) function: diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp index 4948633..93055fc 100644 --- a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE -QML_DEFINE_TYPE(Qt,4,6,Anchors,QmlGraphicsAnchors) +QML_DEFINE_NOCREATE_TYPE(QmlGraphicsAnchors) //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? //TODO: support non-parent, non-sibling (need to find lowest common ancestor) diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp index ba17115..da031f1 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp @@ -158,7 +158,7 @@ QmlGraphicsFlickablePrivate::QmlGraphicsFlickablePrivate() , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) - , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0) + , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(200) , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) , flickDirection(QmlGraphicsFlickable::AutoFlickDirection) { @@ -264,12 +264,19 @@ void QmlGraphicsFlickablePrivate::fixupX() if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->minXExtent())) { timeline.reset(_moveX); - if (_moveX.value() != q->minXExtent()) - timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + if (_moveX.value() != q->minXExtent()) { + if (fixupDuration) + timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + else + _moveY.setValue(q->minYExtent()); + } //emit flickingChanged(); } else if (_moveX.value() < q->maxXExtent()) { timeline.reset(_moveX); - timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + if (fixupDuration) + timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + else + _moveY.setValue(q->maxYExtent()); //emit flickingChanged(); } else { flicked = false; @@ -286,12 +293,19 @@ void QmlGraphicsFlickablePrivate::fixupY() if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) { timeline.reset(_moveY); - if (_moveY.value() != q->minYExtent()) - timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + if (_moveY.value() != q->minYExtent()) { + if (fixupDuration) + timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + else + _moveY.setValue(q->minYExtent()); + } //emit flickingChanged(); } else if (_moveY.value() < q->maxYExtent()) { timeline.reset(_moveY); - timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + if (fixupDuration) + timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + else + _moveY.setValue(q->maxYExtent()); //emit flickingChanged(); } else { flicked = false; @@ -773,24 +787,36 @@ void QmlGraphicsFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEve void QmlGraphicsFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QmlGraphicsFlickable); - d->handleMousePressEvent(event); - event->accept(); + if (d->interactive) { + d->handleMousePressEvent(event); + event->accept(); + } else { + QmlGraphicsItem::mousePressEvent(event); + } } void QmlGraphicsFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QmlGraphicsFlickable); - d->handleMouseMoveEvent(event); - event->accept(); + if (d->interactive) { + d->handleMouseMoveEvent(event); + event->accept(); + } else { + QmlGraphicsItem::mouseMoveEvent(event); + } } void QmlGraphicsFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QmlGraphicsFlickable); - d->clearDelayedPress(); - d->handleMouseReleaseEvent(event); - event->accept(); - ungrabMouse(); + if (d->interactive) { + d->clearDelayedPress(); + d->handleMouseReleaseEvent(event); + event->accept(); + ungrabMouse(); + } else { + QmlGraphicsItem::mouseReleaseEvent(event); + } } void QmlGraphicsFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event) diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h index d59a9e4..ae164cc 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h @@ -123,6 +123,7 @@ public: QGraphicsItem *delayedPressTarget; QBasicTimer delayedPressTimer; int pressDelay; + int fixupDuration; void updateVelocity(); struct Velocity : public QmlTimeLineValue diff --git a/src/declarative/graphicsitems/qmlgraphicsimage.cpp b/src/declarative/graphicsitems/qmlgraphicsimage.cpp index a777de7..ad43027 100644 --- a/src/declarative/graphicsitems/qmlgraphicsimage.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsimage.cpp @@ -139,6 +139,12 @@ QmlGraphicsImage::~QmlGraphicsImage() { } +void QmlGraphicsImage::setSource(const QUrl &url) +{ + QmlGraphicsImageBase::setSource(url); + updatePaintedGeometry(); +} + /*! \qmlproperty QPixmap Image::pixmap @@ -205,9 +211,22 @@ void QmlGraphicsImage::setFillMode(FillMode mode) return; d->fillMode = mode; update(); + updatePaintedGeometry(); emit fillModeChanged(); } +qreal QmlGraphicsImage::paintedWidth() const +{ + Q_D(const QmlGraphicsImage); + return d->paintedWidth; +} + +qreal QmlGraphicsImage::paintedHeight() const +{ + Q_D(const QmlGraphicsImage); + return d->paintedHeight; +} + /*! \qmlproperty enum Image::status @@ -244,6 +263,33 @@ void QmlGraphicsImage::setFillMode(FillMode mode) filtering at the beginning of the animation and reenable it at the conclusion. */ +void QmlGraphicsImage::updatePaintedGeometry() +{ + Q_D(QmlGraphicsImage); + + if (d->fillMode == PreserveAspectFit) { + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); + if (widthScale <= heightScale) { + d->paintedWidth = width(); + d->paintedHeight = widthScale * qreal(d->pix.height()); + } else if(heightScale < widthScale) { + d->paintedWidth = heightScale * qreal(d->pix.width()); + d->paintedHeight = height(); + } + } else { + d->paintedWidth = width(); + d->paintedHeight = height(); + } + emit paintedGeometryChanged(); +} + +void QmlGraphicsImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QmlGraphicsImageBase::geometryChanged(newGeometry, oldGeometry); + updatePaintedGeometry(); +} + /*! \qmlproperty url Image::source @@ -278,7 +324,7 @@ void QmlGraphicsImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid QTransform scale; if (d->fillMode == PreserveAspectFit) { - if (widthScale < heightScale) { + if (widthScale <= heightScale) { heightScale = widthScale; scale.translate(0, (height() - heightScale * d->pix.height()) / 2); } else if(heightScale < widthScale) { diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p.h index 2547b78..36066e1 100644 --- a/src/declarative/graphicsitems/qmlgraphicsimage_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsimage_p.h @@ -59,6 +59,8 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsImage : public QmlGraphicsImageBase Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap NOTIFY pixmapChanged DESIGNABLE false) Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) + Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged) + Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged) public: QmlGraphicsImage(QmlGraphicsItem *parent=0); @@ -71,13 +73,20 @@ public: QPixmap pixmap() const; void setPixmap(const QPixmap &); + qreal paintedWidth() const; + qreal paintedHeight() const; + + void setSource(const QUrl &url); void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); Q_SIGNALS: void fillModeChanged(); + void paintedGeometryChanged(); protected: QmlGraphicsImage(QmlGraphicsImagePrivate &dd, QmlGraphicsItem *parent); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + void updatePaintedGeometry(); private: Q_DISABLE_COPY(QmlGraphicsImage) diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h index f6b4e51..3a5acca 100644 --- a/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h @@ -64,11 +64,13 @@ class QmlGraphicsImagePrivate : public QmlGraphicsImageBasePrivate public: QmlGraphicsImagePrivate() - : fillMode(QmlGraphicsImage::Stretch) + : fillMode(QmlGraphicsImage::Stretch), paintedWidth(0), paintedHeight(0) { } QmlGraphicsImage::FillMode fillMode; + qreal paintedWidth; + qreal paintedHeight; void setPixmap(const QPixmap &pix); }; diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp index dd685d4..bd3c1ea 100644 --- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp @@ -1533,8 +1533,12 @@ void QmlGraphicsItem::setParentItem(QmlGraphicsItem *parent) QmlGraphicsItem *oldParent = parentItem(); if (parent == oldParent || !parent) return; + Q_D(QmlGraphicsItem); QObject::setParent(parent); - QGraphicsObject::setParentItem(parent); + d->setParentItemHelper(parent, /*newParentVariant=*/0, /*thisPointerVariant=*/0); + if (oldParent) + emit oldParent->childrenChanged(); + emit parentChanged(); } /*! diff --git a/src/declarative/graphicsitems/qmlgraphicsitem_p.h b/src/declarative/graphicsitems/qmlgraphicsitem_p.h index ca850f3..91d2119 100644 --- a/src/declarative/graphicsitems/qmlgraphicsitem_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsitem_p.h @@ -116,6 +116,12 @@ public: smooth(false), keyHandler(0), width(0), height(0), implicitWidth(0), implicitHeight(0) { + QGraphicsItemPrivate::acceptedMouseButtons = 0; + QGraphicsItemPrivate::flags = QGraphicsItem::GraphicsItemFlags( + QGraphicsItem::ItemHasNoContents + | QGraphicsItem::ItemIsFocusable + | QGraphicsItem::ItemNegativeZStacksBehindParent); + } void init(QmlGraphicsItem *parent) @@ -125,10 +131,6 @@ public: if (parent) q->setParentItem(parent); _baselineOffset.invalidate(); - q->setAcceptedMouseButtons(Qt::NoButton); - q->setFlags(QGraphicsItem::ItemHasNoContents | - QGraphicsItem::ItemIsFocusable | - QGraphicsItem::ItemNegativeZStacksBehindParent); mouseSetsFocus = false; } diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index 2752551..f75833a 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -447,8 +447,6 @@ public: void updateViewport() { Q_Q(QmlGraphicsListView); - minExtentDirty = true; - maxExtentDirty = true; if (orient == QmlGraphicsListView::Vertical) { q->setViewportHeight(q->minYExtent() - q->maxYExtent()); } else { @@ -721,6 +719,8 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer) } } if (changed) { + minExtentDirty = true; + maxExtentDirty = true; if (visibleItems.count()) visiblePos = (*visibleItems.constBegin())->position(); updateAverage(); @@ -756,8 +756,11 @@ void QmlGraphicsListViewPrivate::layout() if (!isValid()) return; q->refill(); + minExtentDirty = true; + maxExtentDirty = true; updateHighlight(); fixupPosition(); + q->refill(); if (header) updateHeader(); if (footer) @@ -1102,6 +1105,7 @@ void QmlGraphicsListViewPrivate::updateHeader() void QmlGraphicsListViewPrivate::fixupPosition() { + moveReason = Other; if (orient == QmlGraphicsListView::Vertical) fixupY(); else @@ -1116,27 +1120,29 @@ void QmlGraphicsListViewPrivate::fixupY() if (!q->yflick() || _moveY.timeLine()) return; + int oldDuration = fixupDuration; + fixupDuration = moveReason == Mouse ? fixupDuration : 0; + if (haveHighlightRange && highlightRange == QmlGraphicsListView::StrictlyEnforceRange) { if (currentItem && highlight && currentItem->position() != highlight->position()) { - moveReason = Mouse; timeline.reset(_moveY); - timeline.move(_moveY, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveY, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); vTime = timeline.time(); } } else if (snapMode != QmlGraphicsListView::NoSnap) { - moveReason = Mouse; if (FxListItem *item = snapItemAt(position())) { qreal pos = qMin(item->position() - highlightRangeStart, -q->maxYExtent()); qreal dist = qAbs(_moveY + pos); if (dist > 0) { timeline.reset(_moveY); - timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); vTime = timeline.time(); } } } else { QmlGraphicsFlickablePrivate::fixupY(); } + fixupDuration = oldDuration; } void QmlGraphicsListViewPrivate::fixupX() @@ -1147,33 +1153,36 @@ void QmlGraphicsListViewPrivate::fixupX() if (!q->xflick() || _moveX.timeLine()) return; + int oldDuration = fixupDuration; + fixupDuration = moveReason == Mouse ? fixupDuration : 0; + if (haveHighlightRange && highlightRange == QmlGraphicsListView::StrictlyEnforceRange) { if (currentItem && highlight && currentItem->position() != highlight->position()) { - moveReason = Mouse; timeline.reset(_moveX); - timeline.move(_moveX, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveX, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); vTime = timeline.time(); } } else if (snapMode != QmlGraphicsListView::NoSnap) { - moveReason = Mouse; if (FxListItem *item = snapItemAt(position())) { qreal pos = qMin(item->position() - highlightRangeStart, -q->maxXExtent()); qreal dist = qAbs(_moveX + pos); if (dist > 0) { timeline.reset(_moveX); - timeline.move(_moveX, -pos, QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveX, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); vTime = timeline.time(); } } } else { QmlGraphicsFlickablePrivate::fixupX(); } + fixupDuration = oldDuration; } void QmlGraphicsListViewPrivate::flickX(qreal velocity) { Q_Q(QmlGraphicsListView); + moveReason = Mouse; if ((!haveHighlightRange || highlightRange != QmlGraphicsListView::StrictlyEnforceRange) && snapMode == QmlGraphicsListView::NoSnap) { QmlGraphicsFlickablePrivate::flickX(velocity); return; @@ -1271,6 +1280,7 @@ void QmlGraphicsListViewPrivate::flickY(qreal velocity) { Q_Q(QmlGraphicsListView); + moveReason = Mouse; if ((!haveHighlightRange || highlightRange != QmlGraphicsListView::StrictlyEnforceRange) && snapMode == QmlGraphicsListView::NoSnap) { QmlGraphicsFlickablePrivate::flickY(velocity); return; @@ -2024,6 +2034,8 @@ void QmlGraphicsListView::setFooter(QmlComponent *footer) d->footer = 0; } d->footerComponent = footer; + d->minExtentDirty = true; + d->maxExtentDirty = true; d->updateFooter(); d->updateViewport(); } @@ -2044,6 +2056,8 @@ void QmlGraphicsListView::setHeader(QmlComponent *header) d->header = 0; } d->headerComponent = header; + d->minExtentDirty = true; + d->maxExtentDirty = true; d->updateHeader(); d->updateFooter(); d->updateViewport(); @@ -2217,7 +2231,6 @@ void QmlGraphicsListView::keyPressEvent(QKeyEvent *event) } } } - d->moveReason = QmlGraphicsListViewPrivate::Other; event->ignore(); } @@ -2297,6 +2310,7 @@ void QmlGraphicsListView::componentComplete() Q_D(QmlGraphicsListView); QmlGraphicsFlickable::componentComplete(); refill(); + d->moveReason = QmlGraphicsListViewPrivate::SetIndex; if (d->currentIndex < 0) d->updateCurrent(0); else @@ -2313,9 +2327,9 @@ void QmlGraphicsListView::refill() void QmlGraphicsListView::trackedPositionChanged() { Q_D(QmlGraphicsListView); - if (!d->trackedItem) + if (!d->trackedItem || !d->currentItem) return; - if (!isFlicking() && !d->moving && d->moveReason != QmlGraphicsListViewPrivate::Mouse) { + if (!isFlicking() && !d->moving && d->moveReason == QmlGraphicsListViewPrivate::SetIndex) { const qreal trackedPos = d->trackedItem->position(); const qreal viewPos = d->position(); if (d->haveHighlightRange) { @@ -2368,6 +2382,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) { Q_D(QmlGraphicsListView); d->updateUnrequestedIndexes(); + d->moveReason = QmlGraphicsListViewPrivate::Other; if (!d->visibleItems.count() || d->model->count() <= 1) { d->layout(); d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1))); @@ -2375,7 +2390,8 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) return; } - if (!d->mapRangeFromModel(modelIndex, count)) { + int overlapCount = count; + if (!d->mapRangeFromModel(modelIndex, overlapCount)) { int i = d->visibleItems.count() - 1; while (i > 0 && d->visibleItems.at(i)->index == -1) --i; @@ -2413,6 +2429,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) int initialPos = pos; int diff = 0; QList<FxListItem*> added; + bool addedVisible = false; FxListItem *firstVisible = d->firstVisibleItem(); if (firstVisible && pos < firstVisible->position()) { // Insert items before the visible item. @@ -2420,6 +2437,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) int i = 0; int from = d->position() - d->buffer; for (i = count-1; i >= 0 && pos > from; --i) { + addedVisible = true; FxListItem *item = d->createItem(modelIndex + i); d->visibleItems.insert(insertionIdx, item); pos -= item->size() + d->spacing; @@ -2446,6 +2464,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) int i = 0; int to = d->buffer+d->position()+d->size()-1; for (i = 0; i < count && pos <= to; ++i) { + addedVisible = true; FxListItem *item = d->createItem(modelIndex + i); d->visibleItems.insert(index, item); item->setPosition(pos); @@ -2472,7 +2491,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) // Update the indexes of the following visible items. for (; index < d->visibleItems.count(); ++index) { FxListItem *listItem = d->visibleItems.at(index); - if (listItem->item != d->currentItem->item) + if (d->currentItem && listItem->item != d->currentItem->item) listItem->setPosition(listItem->position() + diff); if (listItem->index != -1) listItem->index += count; @@ -2480,43 +2499,21 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) // everything is in order now - emit add() signal for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); - d->layout(); + + if (addedVisible) + d->layout(); emit countChanged(); } void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) { Q_D(QmlGraphicsListView); + d->moveReason = QmlGraphicsListViewPrivate::Other; d->updateUnrequestedIndexes(); - bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count; - if (!d->mapRangeFromModel(modelIndex, count)) { - if (modelIndex + count - 1 < d->visibleIndex) { - // Items removed before our visible items. - d->visibleIndex -= count; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxListItem *listItem = d->visibleItems.at(i); - if (listItem->index != -1) - listItem->index -= count; - } - } - if (d->currentIndex >= modelIndex + count) { - d->currentIndex -= count; - if (d->currentItem) - d->currentItem->index -= count; - } else if (currentRemoved) { - // current item has been removed. - d->releaseItem(d->currentItem); - d->currentItem = 0; - d->currentIndex = -1; - d->updateCurrent(qMin(modelIndex, d->model->count()-1)); - } - d->layout(); - emit countChanged(); - return; - } FxListItem *firstVisible = d->firstVisibleItem(); int preRemovedSize = 0; + bool removedVisible = false; // Remove the items from the visible list, skipping anything already marked for removal QList<FxListItem*>::Iterator it = d->visibleItems.begin(); while (it != d->visibleItems.end()) { @@ -2530,6 +2527,7 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) ++it; } else { // removed item + removedVisible = true; item->attached->emitRemove(); if (item->attached->delayRemove()) { item->index = -1; @@ -2554,7 +2552,7 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) d->currentIndex -= count; if (d->currentItem) d->currentItem->index -= count; - } else if (currentRemoved) { + } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) { // current item has been removed. d->currentItem->attached->setIsCurrentItem(false); d->releaseItem(d->currentItem); @@ -2563,26 +2561,28 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) d->updateCurrent(qMin(modelIndex, d->model->count()-1)); } - // update visibleIndex - for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { - if ((*it)->index != -1) { - d->visibleIndex = (*it)->index; - break; + if (removedVisible) { + // update visibleIndex + for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { + if ((*it)->index != -1) { + d->visibleIndex = (*it)->index; + break; + } } - } - if (d->visibleItems.isEmpty()) { - d->visibleIndex = 0; - d->visiblePos = d->header ? d->header->size() : 0; - d->timeline.clear(); - d->setPosition(0); - if (d->model->count() == 0) - update(); - else - refill(); - } else { - // Correct the positioning of the items - d->layout(); + if (d->visibleItems.isEmpty()) { + d->visibleIndex = 0; + d->visiblePos = d->header ? d->header->size() : 0; + d->timeline.clear(); + d->setPosition(0); + if (d->model->count() == 0) + update(); + else + refill(); + } else { + // Correct the positioning of the items + d->layout(); + } } emit countChanged(); @@ -2615,6 +2615,7 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count) return; } + d->moveReason = QmlGraphicsListViewPrivate::Other; FxListItem *firstVisible = d->firstVisibleItem(); qreal firstItemPos = firstVisible->position(); QHash<int,FxListItem*> moved; diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp index 8ac57e0..112eda2 100644 --- a/src/declarative/graphicsitems/qmlgraphicspathview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicspathview.cpp @@ -56,6 +56,18 @@ QT_BEGIN_NAMESPACE QML_DEFINE_TYPE(Qt,4,6,PathView,QmlGraphicsPathView) + +inline qreal qmlMod(qreal x, qreal y) +{ +#ifdef QT_USE_MATH_H_FLOATS + if(sizeof(qreal) == sizeof(float)) + return fmodf(float(x), float(y)); + else +#endif + return fmod(x, y); +} + + class QmlGraphicsPathViewAttached : public QObject { Q_OBJECT @@ -250,7 +262,7 @@ void QmlGraphicsPathViewPrivate::setOffset(qreal o) { Q_Q(QmlGraphicsPathView); if (_offset != o) { - _offset = fmod(o, 100.0); + _offset = qmlMod(o, qreal(100.0)); if (_offset < 0) _offset = 100.0 + _offset; q->refill(); @@ -450,8 +462,8 @@ void QmlGraphicsPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) velocity = 100; else if (velocity < -100) velocity = -100; - qreal inc = fmod(d->_offset - d->snapPos, 100.0 / d->model->count()); - qreal dist = qAbs(velocity/2 - fmod(velocity/2, 100.0 / d->model->count()) - inc); + qreal inc = qmlMod(d->_offset - d->snapPos, qreal(100.0 / d->model->count())); + qreal dist = qAbs(velocity/2 - qmlMod(velocity/2, qreal(100.0 / d->model->count()) - inc)); d->moveOffset.setValue(d->_offset); d->tl.accel(d->moveOffset, velocity, 10, dist); d->tl.execute(d->fixupOffsetEvent); @@ -542,7 +554,7 @@ void QmlGraphicsPathView::componentComplete() itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -609,7 +621,7 @@ void QmlGraphicsPathView::refill() for (int i=0; i<d->items.count(); i++){ qreal percent = i * (100. / d->items.count()); percent = percent + d->_offset; - percent = fmod(percent,100.); + percent = qmlMod(percent, qreal(100.0)); positions << qAbs(percent/100.0); } @@ -696,7 +708,7 @@ void QmlGraphicsPathView::itemsInserted(int modelIndex, int count) int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -733,7 +745,7 @@ void QmlGraphicsPathView::itemsRemoved(int modelIndex, int count) int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -766,12 +778,12 @@ int QmlGraphicsPathViewPrivate::calcCurrentIndex() { int current = -1; if (model && items.count()) { - _offset = fmod(_offset, 100.0); + _offset = qmlMod(_offset, qreal(100.0)); if (_offset < 0) _offset += 100.0; if (pathItems == -1) { - qreal delta = fmod(_offset - snapPos, 100.0); + qreal delta = qmlMod(_offset - snapPos, qreal(100.0)); if (delta < 0) delta = 100.0 + delta; int ii = model->count() - qRound(delta * model->count() / 100); @@ -784,7 +796,7 @@ int QmlGraphicsPathViewPrivate::calcCurrentIndex() for (int i=0; i<items.count(); i++){ qreal percent = i * (100. / items.count()); percent = percent + _offset; - percent = fmod(percent,100.); + percent = qmlMod(percent, qreal(100.0)); qreal diff = qAbs(snapPos - (percent/100.0)); if (diff < bestDiff){ bestDiff = diff; @@ -843,7 +855,7 @@ void QmlGraphicsPathViewPrivate::snapToCurrent() itemIndex += pathOffset; itemIndex %= items.count(); - qreal targetOffset = fmod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), 100); + qreal targetOffset = qmlMod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; diff --git a/src/declarative/graphicsitems/qmlgraphicstext.cpp b/src/declarative/graphicsitems/qmlgraphicstext.cpp index 854ef45..bfb928a 100644 --- a/src/declarative/graphicsitems/qmlgraphicstext.cpp +++ b/src/declarative/graphicsitems/qmlgraphicstext.cpp @@ -362,12 +362,25 @@ void QmlGraphicsText::setWrap(bool w) The way the text property should be displayed. - Supported text formats are \c AutoText, \c PlainText and \c RichText. + Supported text formats are \c AutoText, \c PlainText, \c RichText and \c StyledText The default is AutoText. If the text format is AutoText the text element will automatically determine whether the text should be treated as rich text. This determination is made using Qt::mightBeRichText(). + StyledText is an optimized format supporting some basic text + styling markup, in the style of html 3.2: + + \code + <font size="4" color="#ff0000">font size and color</font> + <b>bold</b> + <i>italic</i> + <br> + > < & + \endcode + + \c StyledText parser is strict, requiring tags to be correctly nested. + \table \row \o @@ -622,12 +635,25 @@ QSize QmlGraphicsTextPrivate::setupTextLayout(QTextLayout *layout) } layout->endLayout(); + int x = 0; for (int i = 0; i < layout->lineCount(); ++i) { QTextLine line = layout->lineAt(i); widthUsed = qMax(widthUsed, line.naturalTextWidth()); line.setPosition(QPointF(0, height)); height += int(line.height()); + + if (!cache) { + if (hAlign == QmlGraphicsText::AlignLeft) { + x = 0; + } else if (hAlign == QmlGraphicsText::AlignRight) { + x = q->width() - (int)line.naturalTextWidth(); + } else if (hAlign == QmlGraphicsText::AlignHCenter) { + x = (q->width() - (int)line.naturalTextWidth()) / 2; + } + line.setPosition(QPoint(x, (int)line.y())); + } } + return QSize(qCeil(widthUsed), height); } @@ -654,17 +680,21 @@ QPixmap QmlGraphicsTextPrivate::wrappedTextImage(bool drawStyle) if (!size.isEmpty()) { img.fill(Qt::transparent); QPainter p(&img); - if (drawStyle) { - p.setPen(styleColor); - } - else - p.setPen(color); - p.setFont(font); - layout.draw(&p, QPointF(0, 0)); + drawWrappedText(&p, QPointF(0,0), drawStyle); } return img; } +void QmlGraphicsTextPrivate::drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle) +{ + if (drawStyle) + p->setPen(styleColor); + else + p->setPen(color); + p->setFont(font); + layout.draw(p, pos); +} + QPixmap QmlGraphicsTextPrivate::richTextImage(bool drawStyle) { QSize size = doc->size().toSize(); @@ -730,59 +760,87 @@ void QmlGraphicsTextPrivate::checkImgCache() void QmlGraphicsText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QmlGraphicsText); - d->checkImgCache(); - if (d->imgCache.isNull()) - return; - bool oldAA = p->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); - if (d->smooth) - p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + if (d->cache || d->richText || d->style != Normal) { + d->checkImgCache(); + if (d->imgCache.isNull()) + return; - int w = width(); - int h = height(); + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - int x = 0; - int y = 0; - - switch (d->hAlign) { - case AlignLeft: - x = 0; - break; - case AlignRight: - x = w - d->imgCache.width(); - break; - case AlignHCenter: - x = (w - d->imgCache.width()) / 2; - break; - } + int w = width(); + int h = height(); - switch (d->vAlign) { - case AlignTop: - y = 0; - break; - case AlignBottom: - y = h - d->imgCache.height(); - break; - case AlignVCenter: - y = (h - d->imgCache.height()) / 2; - break; - } + int x = 0; + int y = 0; - bool needClip = !clip() && (d->imgCache.width() > width() || - d->imgCache.height() > height()); + switch (d->hAlign) { + case AlignLeft: + x = 0; + break; + case AlignRight: + x = w - d->imgCache.width(); + break; + case AlignHCenter: + x = (w - d->imgCache.width()) / 2; + break; + } - if (needClip) { - p->save(); - p->setClipRect(boundingRect(), Qt::IntersectClip); - } - p->drawPixmap(x, y, d->imgCache); - if (needClip) - p->restore(); + switch (d->vAlign) { + case AlignTop: + y = 0; + break; + case AlignBottom: + y = h - d->imgCache.height(); + break; + case AlignVCenter: + y = (h - d->imgCache.height()) / 2; + break; + } + + bool needClip = !clip() && (d->imgCache.width() > width() || + d->imgCache.height() > height()); + + if (needClip) { + p->save(); + p->setClipRect(boundingRect(), Qt::IntersectClip); + } + p->drawPixmap(x, y, d->imgCache); + if (needClip) + p->restore(); + + if (d->smooth) { + p->setRenderHint(QPainter::Antialiasing, oldAA); + p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); + } + } else { + int h = height(); + int y = 0; + + switch (d->vAlign) { + case AlignTop: + y = 0; + break; + case AlignBottom: + y = h - d->cachedLayoutSize.height(); + break; + case AlignVCenter: + y = (h - d->cachedLayoutSize.height()) / 2; + break; + } + bool needClip = !clip() && (d->cachedLayoutSize.width() > width() || + d->cachedLayoutSize.height() > height()); - if (d->smooth) { - p->setRenderHint(QPainter::Antialiasing, oldAA); - p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); + if (needClip) { + p->save(); + p->setClipRect(boundingRect(), Qt::IntersectClip); + } + d->drawWrappedText(p, QPointF(0,y), false); + if (needClip) + p->restore(); } } diff --git a/src/declarative/graphicsitems/qmlgraphicstext_p_p.h b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h index 73c3dd7..1e29e58 100644 --- a/src/declarative/graphicsitems/qmlgraphicstext_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h @@ -72,9 +72,12 @@ public: QmlGraphicsTextPrivate() : color((QRgb)0), style(QmlGraphicsText::Normal), imgDirty(true), hAlign(QmlGraphicsText::AlignLeft), vAlign(QmlGraphicsText::AlignTop), elideMode(QmlGraphicsText::ElideNone), - dirty(true), wrap(false), richText(false), singleline(false), doc(0), + dirty(true), wrap(false), richText(false), singleline(false), cache(true), doc(0), format(QmlGraphicsText::AutoText) { +#ifdef QML_NO_TEXT_CACHE + cache = false; +#endif } ~QmlGraphicsTextPrivate(); @@ -93,6 +96,7 @@ public: void drawOutline(int yOffset); QPixmap wrappedTextImage(bool drawStyle); + void drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle); QPixmap richTextImage(bool drawStyle); QSize setupTextLayout(QTextLayout *layout); @@ -112,6 +116,7 @@ public: bool wrap:1; bool richText:1; bool singleline:1; + bool cache:1; QTextDocument *doc; QTextLayout layout; QSize cachedLayoutSize; diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g index 70cf06a..90949d5 100644 --- a/src/declarative/qml/parser/qmljs.g +++ b/src/declarative/qml/parser/qmljs.g @@ -1,45 +1,24 @@ ---------------------------------------------------------------------------- -- --- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). --- Contact: Qt Software Information (qt-info@nokia.com) +-- 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 QtDeclarative 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 either Technology Preview License Agreement or the --- Beta Release License Agreement. --- +-- $QT_BEGIN_LICENSE:LGPL-ONLY$ -- GNU Lesser General Public License Usage --- Alternatively, this file may be used under the terms of the GNU Lesser +-- 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.0, included in the file LGPL_EXCEPTION.txt in this --- package. --- --- GNU General Public License Usage --- Alternatively, this file may be used under the terms of the GNU --- General Public License version 3.0 as published by the Free Software --- Foundation and appearing in the file LICENSE.GPL included in the --- packaging of this file. Please review the following information to --- ensure the GNU General Public License version 3.0 requirements will be --- met: http://www.gnu.org/copyleft/gpl.html. --- --- If you are unsure which license is appropriate for your use, please --- contact the sales department at qt-sales@nokia.com. +-- If you have questions regarding the use of this file, please contact +-- Nokia at qt-info@nokia.com. -- $QT_END_LICENSE$ -- --- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE --- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. --- ---------------------------------------------------------------------------- %parser QmlJSGrammar @@ -92,6 +71,8 @@ %token T_FEED_UI_OBJECT_MEMBER %token T_FEED_JS_STATEMENT %token T_FEED_JS_EXPRESSION +%token T_FEED_JS_SOURCE_ELEMENT +%token T_FEED_JS_PROGRAM %nonassoc SHIFT_THERE %nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY @@ -99,11 +80,11 @@ %start TopLevel -/. -/**************************************************************************** +/./**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** 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 QtDeclarative module of the Qt Toolkit. ** @@ -111,8 +92,8 @@ ** 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 either Technology Preview License Agreement or the -** Beta Release License Agreement. +** 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 @@ -122,21 +103,20 @@ ** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. +** 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. +** +** +** +** +** +** ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -153,11 +133,11 @@ ./ -/: -/**************************************************************************** +/:/**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** 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 QtDeclarative module of the Qt Toolkit. ** @@ -165,8 +145,8 @@ ** 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 either Technology Preview License Agreement or the -** Beta Release License Agreement. +** 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 @@ -176,25 +156,25 @@ ** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. +** 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. +** +** +** +** +** +** ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ + // // W A R N I N G // ------------- @@ -229,7 +209,7 @@ namespace QmlJS { class Engine; class NameId; -class Parser: protected $table +class QML_PARSER_EXPORT Parser: protected $table { public: union Value { @@ -287,7 +267,9 @@ public: bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } + bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } + bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast<AST::UiProgram *>(program); } @@ -316,6 +298,9 @@ public: return program->uiObjectMemberCast(); } + AST::Node *rootNode() const + { return program; } + QList<DiagnosticMessage> diagnosticMessages() const { return diagnostic_messages; } @@ -561,6 +546,14 @@ case $rule_number: { } break; ./ +TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ; /. case $rule_number: { @@ -569,6 +562,14 @@ case $rule_number: { } break; ./ +TopLevel: T_FEED_JS_PROGRAM Program ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + UiProgram: UiImportListOpt UiRootMember ; /. case $rule_number: { @@ -2885,13 +2886,12 @@ case $rule_number: { } break; ./ ---QmlJSProgram: SourceElements ; ---/. ---case $rule_number: { --- sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); --- driver->changeAbstractSyntaxTree(sym(1).Node); ---} break; ---./ +Program: SourceElements ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; +./ SourceElements: SourceElement ; /. @@ -2985,7 +2985,12 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { - const QString msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + QString msg; + int token = token_buffer[0].token; + if (token < 0 || token >= TERMINAL_COUNT) + msg = qApp->translate("QmlParser", "Syntax error"); + else + msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; @@ -3031,7 +3036,8 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || - tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || + tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); diff --git a/src/declarative/qml/parser/qmljsast.cpp b/src/declarative/qml/parser/qmljsast.cpp index 2a39aae..e80b05e 100644 --- a/src/declarative/qml/parser/qmljsast.cpp +++ b/src/declarative/qml/parser/qmljsast.cpp @@ -798,7 +798,6 @@ void DebuggerStatement::accept0(Visitor *visitor) visitor->endVisit(this); } - void UiProgram::accept0(Visitor *visitor) { if (visitor->visit(this)) { diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp index b8c6560..b416959 100644 --- a/src/declarative/qml/parser/qmljsgrammar.cpp +++ b/src/declarative/qml/parser/qmljsgrammar.cpp @@ -1,4 +1,3 @@ -// This file was generated by qlalr - DO NOT EDIT! /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). @@ -40,8 +39,11 @@ ** ****************************************************************************/ +// This file was generated by qlalr - DO NOT EDIT! #include "qmljsgrammar_p.h" +QT_BEGIN_NAMESPACE + const char *const QmlJSGrammar::spell [] = { "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue", "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", @@ -52,591 +54,580 @@ const char *const QmlJSGrammar::spell [] = { ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch", "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public", - "import", "as", 0, 0, 0, 0, 0, 0}; + "import", "as", 0, 0, 0, 0, 0, 0, 0, 0}; -const int QmlJSGrammar::lhs [] = { - 98, 98, 98, 98, 99, 103, 103, 106, 106, 108, - 107, 107, 107, 107, 107, 107, 107, 107, 110, 105, - 104, 113, 113, 114, 114, 115, 115, 112, 102, 102, - 102, 102, 102, 102, 102, 121, 121, 121, 122, 122, - 123, 123, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 111, 111, 111, 111, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 116, 128, 128, 128, 128, 127, 127, 130, - 130, 132, 132, 132, 132, 132, 132, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, - 109, 109, 109, 109, 109, 137, 137, 138, 138, 138, - 138, 136, 136, 139, 139, 140, 140, 141, 141, 141, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 143, 143, 143, 143, 144, 144, 144, 145, 145, 145, - 145, 146, 146, 146, 146, 146, 146, 146, 147, 147, - 147, 147, 147, 147, 148, 148, 148, 148, 148, 149, - 149, 149, 149, 149, 150, 150, 151, 151, 152, 152, - 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, - 158, 158, 159, 159, 160, 160, 161, 161, 131, 131, - 162, 162, 163, 163, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 101, 101, 164, 164, 165, 165, - 166, 166, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 100, 117, 178, 178, - 177, 177, 125, 125, 179, 179, 180, 180, 182, 182, - 181, 183, 186, 184, 184, 187, 185, 185, 118, 119, - 119, 120, 120, 167, 167, 167, 167, 167, 167, 167, - 168, 168, 168, 168, 169, 169, 169, 169, 170, 170, - 171, 173, 188, 188, 191, 191, 189, 189, 192, 190, - 172, 172, 172, 174, 174, 175, 175, 175, 193, 194, - 176, 176, 124, 135, 198, 198, 195, 195, 196, 196, - 199, 200, 200, 201, 201, 197, 197, 129, 129, 202}; +const short QmlJSGrammar::lhs [] = { + 100, 100, 100, 100, 100, 100, 101, 107, 107, 110, + 110, 112, 111, 111, 111, 111, 111, 111, 111, 111, + 114, 109, 108, 117, 117, 118, 118, 119, 119, 116, + 105, 105, 105, 105, 105, 105, 105, 125, 125, 125, + 126, 126, 127, 127, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 115, 115, 115, 115, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 120, 132, 132, 132, 132, 131, + 131, 134, 134, 136, 136, 136, 136, 136, 136, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 138, 138, 113, 113, 113, 113, 113, 141, 141, 142, + 142, 142, 142, 140, 140, 143, 143, 144, 144, 145, + 145, 145, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 147, 147, 147, 147, 148, 148, 148, 149, + 149, 149, 149, 150, 150, 150, 150, 150, 150, 150, + 151, 151, 151, 151, 151, 151, 152, 152, 152, 152, + 152, 153, 153, 153, 153, 153, 154, 154, 155, 155, + 156, 156, 157, 157, 158, 158, 159, 159, 160, 160, + 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, + 135, 135, 166, 166, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 103, 103, 168, 168, + 169, 169, 170, 170, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 121, + 182, 182, 181, 181, 129, 129, 183, 183, 184, 184, + 186, 186, 185, 187, 190, 188, 188, 191, 189, 189, + 122, 123, 123, 124, 124, 171, 171, 171, 171, 171, + 171, 171, 172, 172, 172, 172, 173, 173, 173, 173, + 174, 174, 175, 177, 192, 192, 195, 195, 193, 193, + 196, 194, 176, 176, 176, 178, 178, 179, 179, 179, + 197, 198, 180, 180, 128, 139, 202, 202, 199, 199, + 200, 200, 203, 106, 204, 204, 104, 104, 201, 201, + 133, 133, 205}; -const int QmlJSGrammar:: rhs[] = { - 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, - 2, 2, 3, 3, 5, 5, 4, 4, 2, 0, - 1, 1, 2, 1, 3, 2, 3, 2, 1, 5, - 4, 3, 3, 3, 3, 1, 1, 1, 0, 1, - 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, - 5, 5, 6, 6, 7, 7, 7, 7, 1, 1, +const short QmlJSGrammar::rhs [] = { + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 2, 1, 2, 2, 3, 3, 5, 5, 4, 4, + 2, 0, 1, 1, 2, 1, 3, 2, 3, 2, + 1, 5, 4, 3, 3, 3, 3, 1, 1, 1, + 0, 1, 2, 4, 6, 6, 3, 3, 7, 7, + 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, - 4, 3, 1, 1, 2, 3, 4, 1, 2, 3, - 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, + 5, 3, 4, 3, 1, 1, 2, 3, 4, 1, + 2, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 4, 3, 5, 1, 2, 4, 4, 4, - 3, 0, 1, 1, 3, 1, 1, 1, 2, 2, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, - 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, - 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, - 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, + 1, 1, 1, 1, 4, 3, 5, 1, 2, 4, + 4, 4, 3, 0, 1, 1, 3, 1, 1, 1, + 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 3, 3, 3, 1, 3, 3, 1, + 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, + 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, + 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 5, 1, 5, 1, 3, - 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 0, 1, 1, 3, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, - 0, 1, 3, 3, 1, 1, 1, 3, 1, 3, - 2, 2, 2, 0, 1, 2, 0, 1, 1, 2, - 2, 7, 5, 7, 7, 5, 9, 10, 7, 8, - 2, 2, 3, 3, 2, 2, 3, 3, 3, 3, - 5, 5, 3, 5, 1, 2, 0, 1, 4, 3, - 3, 3, 3, 3, 3, 3, 3, 4, 5, 2, - 2, 2, 8, 8, 1, 3, 0, 1, 0, 1, - 1, 1, 2, 1, 1, 0, 1, 0, 1, 2}; + 1, 3, 1, 3, 1, 3, 1, 5, 1, 5, + 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 0, 1, + 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 2, 0, 1, 3, 3, 1, 1, 1, 3, + 1, 3, 2, 2, 2, 0, 1, 2, 0, 1, + 1, 2, 2, 7, 5, 7, 7, 5, 9, 10, + 7, 8, 2, 2, 3, 3, 2, 2, 3, 3, + 3, 3, 5, 5, 3, 5, 1, 2, 0, 1, + 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, + 5, 2, 2, 2, 8, 8, 1, 3, 0, 1, + 0, 1, 1, 1, 1, 2, 1, 1, 0, 1, + 0, 1, 2}; -const int QmlJSGrammar::action_default [] = { - 0, 0, 0, 0, 20, 0, 168, 235, 199, 207, - 203, 147, 219, 195, 3, 132, 66, 148, 211, 215, - 136, 165, 146, 151, 131, 185, 172, 0, 73, 74, - 69, 336, 61, 338, 0, 0, 0, 0, 71, 0, - 0, 67, 70, 0, 0, 62, 64, 63, 72, 65, - 0, 68, 0, 0, 161, 0, 0, 148, 167, 150, - 149, 0, 0, 0, 163, 164, 162, 166, 0, 196, - 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, - 0, 176, 0, 0, 0, 170, 171, 169, 174, 178, - 177, 175, 173, 188, 187, 189, 0, 204, 0, 200, - 0, 0, 142, 129, 141, 130, 98, 99, 100, 125, - 101, 126, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 127, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 128, 0, 0, 140, - 236, 143, 0, 144, 0, 145, 139, 0, 232, 225, - 223, 230, 231, 229, 228, 234, 227, 226, 224, 233, - 220, 0, 208, 0, 0, 212, 0, 0, 216, 0, - 0, 142, 134, 0, 133, 0, 138, 152, 0, 337, - 327, 328, 0, 325, 0, 326, 0, 329, 243, 250, - 249, 257, 245, 0, 246, 330, 0, 335, 247, 248, - 253, 251, 332, 331, 334, 254, 0, 265, 0, 0, - 0, 0, 336, 61, 0, 338, 62, 237, 279, 63, - 0, 0, 0, 266, 0, 0, 255, 256, 0, 244, - 252, 280, 281, 324, 333, 0, 295, 296, 297, 298, - 0, 291, 292, 293, 294, 321, 322, 0, 0, 0, - 0, 0, 284, 285, 241, 239, 201, 209, 205, 221, - 197, 242, 0, 148, 213, 217, 190, 179, 0, 0, - 198, 0, 0, 0, 0, 191, 0, 0, 0, 0, - 0, 183, 181, 184, 182, 180, 193, 192, 194, 0, - 206, 0, 202, 0, 240, 148, 0, 222, 237, 238, - 0, 237, 0, 0, 287, 0, 0, 0, 289, 0, - 210, 0, 0, 214, 0, 0, 218, 277, 0, 269, - 278, 272, 0, 276, 0, 237, 270, 0, 237, 0, - 0, 288, 0, 0, 0, 290, 337, 327, 0, 0, - 329, 0, 323, 0, 313, 0, 0, 0, 283, 0, - 282, 0, 339, 0, 97, 259, 262, 0, 98, 265, - 101, 126, 103, 104, 69, 108, 109, 61, 110, 113, - 67, 70, 62, 237, 63, 72, 116, 65, 118, 68, - 120, 121, 266, 123, 124, 128, 0, 90, 0, 0, - 92, 96, 94, 81, 93, 95, 0, 91, 80, 260, - 258, 136, 137, 142, 0, 135, 0, 312, 0, 299, - 300, 0, 311, 0, 0, 0, 302, 307, 305, 308, - 0, 0, 306, 307, 0, 303, 0, 304, 261, 310, - 0, 261, 309, 0, 314, 315, 0, 261, 316, 317, - 0, 0, 318, 0, 0, 0, 319, 320, 154, 153, - 0, 0, 0, 286, 0, 0, 0, 301, 274, 267, - 0, 275, 271, 0, 273, 263, 0, 264, 268, 84, - 0, 0, 88, 75, 0, 77, 86, 0, 78, 87, - 89, 79, 85, 76, 0, 82, 158, 156, 160, 157, - 155, 159, 2, 59, 83, 0, 0, 62, 64, 63, - 29, 4, 0, 60, 0, 38, 37, 36, 0, 0, - 51, 0, 52, 0, 57, 58, 0, 38, 0, 0, - 0, 0, 0, 47, 48, 0, 49, 0, 50, 0, - 53, 54, 0, 0, 0, 0, 0, 55, 56, 0, - 45, 39, 46, 40, 0, 0, 0, 0, 42, 0, - 43, 44, 41, 0, 0, 28, 32, 33, 34, 35, - 136, 261, 0, 0, 98, 265, 101, 126, 103, 104, - 69, 108, 109, 61, 110, 113, 67, 70, 62, 237, - 63, 72, 116, 65, 118, 68, 120, 121, 266, 123, - 124, 128, 136, 0, 24, 0, 0, 30, 25, 31, - 26, 22, 0, 27, 23, 6, 0, 8, 0, 7, - 0, 1, 19, 10, 0, 11, 0, 12, 0, 17, - 18, 0, 13, 14, 0, 15, 16, 9, 21, 5, - 340}; +const short QmlJSGrammar::action_default [] = { + 0, 0, 0, 0, 0, 0, 22, 0, 170, 237, + 201, 209, 205, 149, 221, 197, 3, 134, 68, 150, + 213, 217, 138, 167, 148, 153, 133, 187, 174, 0, + 75, 76, 71, 339, 63, 341, 0, 0, 0, 0, + 73, 0, 0, 69, 72, 0, 0, 64, 66, 65, + 74, 67, 0, 70, 0, 0, 163, 0, 0, 150, + 169, 152, 151, 0, 0, 0, 165, 166, 164, 168, + 0, 198, 0, 0, 0, 0, 188, 0, 0, 0, + 0, 0, 0, 178, 0, 0, 0, 172, 173, 171, + 176, 180, 179, 177, 175, 190, 189, 191, 0, 206, + 0, 202, 0, 0, 144, 131, 143, 132, 100, 101, + 102, 127, 103, 128, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 129, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 130, 0, + 0, 142, 238, 145, 0, 146, 0, 147, 141, 0, + 234, 227, 225, 232, 233, 231, 230, 236, 229, 228, + 226, 235, 222, 0, 210, 0, 0, 214, 0, 0, + 218, 0, 0, 144, 136, 0, 135, 0, 140, 154, + 0, 340, 329, 330, 0, 327, 0, 328, 0, 331, + 245, 252, 251, 259, 247, 0, 248, 332, 0, 338, + 249, 250, 255, 253, 335, 333, 337, 256, 0, 267, + 0, 0, 0, 0, 339, 63, 0, 341, 64, 239, + 281, 65, 0, 0, 0, 268, 0, 0, 257, 258, + 0, 246, 254, 282, 283, 326, 336, 0, 297, 298, + 299, 300, 0, 293, 294, 295, 296, 323, 324, 0, + 0, 0, 0, 0, 286, 287, 243, 241, 203, 211, + 207, 223, 199, 244, 0, 150, 215, 219, 192, 181, + 0, 0, 200, 0, 0, 0, 0, 193, 0, 0, + 0, 0, 0, 185, 183, 186, 184, 182, 195, 194, + 196, 0, 208, 0, 204, 0, 242, 150, 0, 224, + 239, 240, 0, 239, 0, 0, 289, 0, 0, 0, + 291, 0, 212, 0, 0, 216, 0, 0, 220, 279, + 0, 271, 280, 274, 0, 278, 0, 239, 272, 0, + 239, 0, 0, 290, 0, 0, 0, 292, 340, 329, + 0, 0, 331, 0, 325, 0, 315, 0, 0, 0, + 285, 0, 284, 0, 342, 0, 99, 261, 264, 0, + 100, 267, 103, 128, 105, 106, 71, 110, 111, 63, + 112, 115, 69, 72, 64, 239, 65, 74, 118, 67, + 120, 70, 122, 123, 268, 125, 126, 130, 0, 92, + 0, 0, 94, 98, 96, 83, 95, 97, 0, 93, + 82, 262, 260, 138, 139, 144, 0, 137, 0, 314, + 0, 301, 302, 0, 313, 0, 0, 0, 304, 309, + 307, 310, 0, 0, 308, 309, 0, 305, 0, 306, + 263, 312, 0, 263, 311, 0, 316, 317, 0, 263, + 318, 319, 0, 0, 320, 0, 0, 0, 321, 322, + 156, 155, 0, 0, 0, 288, 0, 0, 0, 303, + 276, 269, 0, 277, 273, 0, 275, 265, 0, 266, + 270, 86, 0, 0, 90, 77, 0, 79, 88, 0, + 80, 89, 91, 81, 87, 78, 0, 84, 160, 158, + 162, 159, 157, 161, 6, 334, 4, 2, 61, 85, + 0, 0, 64, 66, 65, 31, 5, 0, 62, 0, + 40, 39, 38, 0, 0, 53, 0, 54, 0, 59, + 60, 0, 40, 0, 0, 0, 0, 0, 49, 50, + 0, 51, 0, 52, 0, 55, 56, 0, 0, 0, + 0, 0, 57, 58, 0, 47, 41, 48, 42, 0, + 0, 0, 0, 44, 0, 45, 46, 43, 0, 0, + 30, 34, 35, 36, 37, 138, 263, 0, 0, 100, + 267, 103, 128, 105, 106, 71, 110, 111, 63, 112, + 115, 69, 72, 64, 239, 65, 74, 118, 67, 120, + 70, 122, 123, 268, 125, 126, 130, 138, 0, 26, + 0, 0, 32, 27, 33, 28, 24, 0, 29, 25, + 8, 0, 10, 0, 9, 0, 1, 21, 12, 0, + 13, 0, 14, 0, 19, 20, 0, 15, 16, 0, + 17, 18, 11, 23, 7, 343}; -const int QmlJSGrammar::goto_default [] = { - 5, 611, 355, 193, 501, 610, 629, 605, 609, 607, - 612, 20, 608, 16, 500, 602, 593, 555, 502, 188, - 192, 194, 198, 518, 544, 543, 197, 229, 24, 471, - 470, 353, 352, 7, 351, 354, 104, 15, 142, 22, - 11, 141, 17, 23, 54, 21, 6, 26, 25, 266, - 13, 260, 8, 256, 10, 258, 9, 257, 18, 264, - 19, 265, 12, 259, 255, 296, 408, 261, 262, 199, - 190, 189, 201, 230, 200, 205, 226, 227, 191, 357, - 356, 228, 460, 459, 318, 319, 462, 321, 461, 320, - 416, 420, 423, 419, 418, 438, 439, 182, 196, 178, - 181, 195, 203, 202, 0}; +const short QmlJSGrammar::goto_default [] = { + 7, 616, 206, 195, 204, 506, 494, 615, 634, 610, + 614, 612, 617, 22, 613, 18, 505, 607, 598, 560, + 507, 190, 194, 196, 200, 523, 549, 548, 199, 231, + 26, 473, 472, 355, 354, 9, 353, 356, 106, 17, + 144, 24, 13, 143, 19, 25, 56, 23, 8, 28, + 27, 268, 15, 262, 10, 258, 12, 260, 11, 259, + 20, 266, 21, 267, 14, 261, 257, 298, 410, 263, + 264, 201, 192, 191, 203, 232, 202, 207, 228, 229, + 193, 359, 358, 230, 462, 461, 320, 321, 464, 323, + 463, 322, 418, 422, 425, 421, 420, 440, 441, 184, + 198, 180, 183, 197, 205, 0}; -const int QmlJSGrammar::action_index [] = { - 251, 1237, 2238, 974, -45, 51, 122, -98, 52, -11, - -39, 182, -98, 389, 36, -98, -98, 628, 58, 75, - 246, 228, -98, -98, -98, 438, 309, 1237, -98, -98, - -98, 348, -98, 2050, 1772, 1237, 1237, 1237, -98, 800, - 1237, -98, -98, 1237, 1237, -98, -98, -98, -98, -98, - 1237, -98, 1237, 1237, -98, 1237, 1237, 97, 226, -98, - -98, 1237, 1237, 1237, -98, -98, -98, 200, 1237, 389, - 1237, 1237, 1237, 1237, 418, 1237, 1237, 1237, 1237, 1237, - 1237, 212, 1237, 1237, 1237, 144, 121, 71, 309, 309, - 164, 156, 179, 448, 428, 408, 1237, -51, 1237, 101, - 1956, 1237, 1237, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, -98, -98, -98, -98, 236, 1237, -98, - -98, 31, 16, -98, 1237, -98, -98, 1237, -98, -98, - -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, 1237, 2, 1237, 1237, 41, 35, 1237, -98, 1956, - 1237, 1237, -98, 102, -98, 6, -98, -98, 20, -98, - 299, 53, 14, -98, 321, -98, -22, 2332, -98, -98, - -98, -98, -98, 216, -98, -98, -28, -98, -98, -98, - -98, -98, -98, 2332, -98, -98, 469, -98, 533, 115, - 2238, -2, 335, -3, -36, 2520, 50, 1237, -98, 64, - 33, 1237, 21, -98, 5, -14, -98, -98, 306, -98, - -98, -98, -98, -98, -98, 74, -98, -98, -98, -98, - 117, -98, -98, -98, -98, -98, -98, -57, -18, 1237, - 140, 109, -98, -98, 1324, -98, 104, 67, 27, -98, - 330, 84, 29, 585, 80, 92, 464, 171, 295, 1237, - 314, 1237, 1237, 1237, 1237, 346, 1237, 1237, 1237, 1237, - 1237, 309, 309, 309, 309, 309, 386, 464, 464, 1237, - 27, 1237, 87, 1237, -98, 529, 1237, -98, 1237, 83, - 38, 1237, 48, 2238, -98, 1237, 143, 2238, -98, 1237, - 30, 1237, 1237, 81, 77, 1237, -98, 56, 126, 90, - -98, -98, 1237, -98, 290, 1237, -98, 42, 1237, 44, - 2238, -98, 1237, 133, 2238, -98, 22, 285, -37, -9, - 2332, -30, -98, 2238, -98, 1237, 141, 2238, 10, 2238, - -98, 26, 24, -24, -98, -98, 2238, 25, 453, 23, - 533, 106, 1237, 2238, 9, -29, 361, -4, -31, 800, - -6, 55, -98, 1415, -98, -1, -23, 8, 1237, 7, - -21, 1237, 1, 1237, -27, -19, 1237, -98, 2144, 28, - -98, -98, -98, -98, -98, -98, 1237, -98, -98, -98, - -98, 211, -98, 1237, 17, -98, 2238, -98, 98, -98, - -98, 2238, -98, 1237, 105, 37, -98, 63, -98, 62, - 99, 1237, -98, 60, 57, -98, 4, -98, 2238, -98, - 116, 2238, -98, 180, -98, -98, 112, 2238, 18, -98, - 11, 13, -98, 325, 3, 19, -98, -98, -98, -98, - 1237, 132, 2238, -98, 1237, 139, 2238, -98, 32, -98, - 174, -98, -98, 1237, -98, -98, 229, -98, -98, -98, - 108, 1682, -98, -98, 1862, -98, -98, 1505, -98, -98, - -98, -98, -98, -98, 125, -98, -98, -98, -98, -98, - -98, -98, -98, -98, 111, 46, 792, 184, 34, 85, - -98, -98, 136, -98, 185, -98, -98, -98, 65, 204, - -98, 1237, -98, 207, -98, -98, 193, 61, 43, 225, - 73, 88, 66, -98, -98, 214, -98, 1237, -98, 158, - -98, -98, 181, 91, 72, 1237, 172, -98, -98, 187, - -98, 157, -98, 47, -50, 274, 178, 250, -98, 113, - -98, -98, -98, 1592, 1062, -98, -98, -98, -98, -98, - 271, 2426, 1772, 15, 461, 146, 445, 76, 1237, 2238, - -5, 0, 370, 12, -15, 706, 89, 78, -98, 1415, - -98, 100, 59, 82, 1237, 86, 54, 1237, 79, 1237, - 45, 39, 279, 149, -98, 68, 617, -98, -98, -98, - -98, -98, 1150, -98, -98, -98, 886, -98, 240, -61, - 714, -98, -98, 129, 259, -98, 190, -98, 69, -98, - -98, 255, -98, -98, 94, -98, -98, -98, -98, -98, - -98, +const short QmlJSGrammar::action_index [] = { + 439, 1109, 2228, 2228, 2132, 814, -74, 18, 147, -100, + 31, -17, -49, 232, -100, 318, 85, -100, -100, 554, + 33, 94, 331, 215, -100, -100, -100, 448, 231, 1109, + -100, -100, -100, 320, -100, 1940, 1472, 1109, 1109, 1109, + -100, 724, 1109, -100, -100, 1109, 1109, -100, -100, -100, + -100, -100, 1109, -100, 1109, 1109, -100, 1109, 1109, 129, + 157, -100, -100, 1109, 1109, 1109, -100, -100, -100, 200, + 1109, 293, 1109, 1109, 1109, 1109, 466, 1109, 1109, 1109, + 1109, 1109, 1109, 179, 1109, 1109, 1109, 119, 125, 95, + 188, 198, 184, 203, 178, 567, 567, 484, 1109, -5, + 1109, 67, 1844, 1109, 1109, -100, -100, -100, -100, -100, + -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, + -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, + -100, -100, -100, -100, -100, -100, -100, -100, -100, 110, + 1109, -100, -100, 70, 61, -100, 1109, -100, -100, 1109, + -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, + -100, -100, -100, 1109, 55, 1109, 1109, 73, 63, 1109, + -100, 1844, 1109, 1109, -100, 141, -100, 41, -100, -100, + 87, -100, 255, 80, 78, -100, 287, -100, 83, 2228, + -100, -100, -100, -100, -100, 225, -100, -100, 52, -100, + -100, -100, -100, -100, -100, 2228, -100, -100, 420, -100, + 408, 113, 2132, 50, 330, 65, 46, 2420, 72, 1109, + -100, 74, 75, 1109, 77, -100, 53, 56, -100, -100, + 323, -100, -100, -100, -100, -100, -100, 96, -100, -100, + -100, -100, 99, -100, -100, -100, -100, -100, -100, 60, + 47, 1109, 118, 93, -100, -100, 1291, -100, 79, 66, + 64, -100, 413, 76, 51, 664, 89, 97, 393, 183, + 337, 1109, 413, 1109, 1109, 1109, 1109, 411, 1109, 1109, + 1109, 1109, 1109, 252, 272, 212, 217, 221, 490, 490, + 383, 1109, 64, 1109, 84, 1109, -100, 536, 1109, -100, + 1109, 69, 68, 1109, 44, 2132, -100, 1109, 124, 2132, + -100, 1109, 54, 1109, 1109, 71, 88, 1109, -100, 82, + 122, 154, -100, -100, 1109, -100, 343, 1109, -100, 81, + 1109, 90, 2132, -100, 1109, 112, 2132, -100, 86, 333, + -39, -10, 2228, -33, -100, 2132, -100, 1109, 246, 2132, + 4, 2132, -100, 10, 16, -21, -100, -100, 2132, -26, + 480, 19, 462, 128, 1109, 2132, 6, -9, 400, 8, + -22, 840, -3, -6, -100, 1202, -100, -7, -28, 5, + 1109, 2, -23, 1109, 0, 1109, -34, -30, 1109, -100, + 2036, 21, -100, -100, -100, -100, -100, -100, 1109, -100, + -100, -100, -100, 209, -100, 1109, 40, -100, 2132, -100, + 101, -100, -100, 2132, -100, 1109, 120, 43, -100, 62, + -100, 59, 109, 1109, -100, 57, 58, -100, 39, -100, + 2132, -100, 117, 2132, -100, 199, -100, -100, 107, 2132, + 34, -100, 24, 11, -100, 346, -19, 14, -100, -100, + -100, -100, 1109, 133, 2132, -100, 1109, 126, 2132, -100, + 20, -100, 173, -100, -100, 1109, -100, -100, 303, -100, + -100, -100, 100, 1656, -100, -100, 1564, -100, -100, 1748, + -100, -100, -100, -100, -100, -100, 131, -100, -100, -100, + -100, -100, -100, -100, -100, 2228, -100, -100, -100, 158, + -20, 752, 165, -16, 22, -100, -100, 98, -100, 189, + -100, -100, -100, 28, 170, -100, 1109, -100, 230, -100, + -100, 247, 1, 13, 238, 37, -24, 106, -100, -100, + 273, -100, 1109, -100, 265, -100, -100, 242, -4, 12, + 1109, 241, -100, -100, 234, -100, 245, -100, 3, 9, + 311, 190, 316, -100, 134, -100, -100, -100, 1380, 1020, + -100, -100, -100, -100, -100, 359, 2324, 1472, 15, 444, + 38, 394, 138, 1109, 2132, 36, 17, 397, 42, 23, + 840, 32, 29, -100, 1202, -100, 26, 35, 48, 1109, + 45, 25, 1109, 49, 1109, 27, 30, 314, 132, -100, + 7, 752, -100, -100, -100, -100, -100, 930, -100, -100, + -100, 752, -100, 253, -87, 617, -100, -100, 102, 290, + -100, 191, -100, 140, -100, -100, 275, -100, -100, 91, + -100, -100, -100, -100, -100, -100, - -105, 23, 25, 216, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -44, -105, -105, - -105, -105, -105, -105, -105, -105, -105, 70, -105, -105, - -105, 28, -105, -105, 20, 39, 97, 163, -105, 178, - 159, -105, -105, 156, 164, -105, -105, -105, -105, -105, - 132, -105, 153, 135, -105, 139, 140, -105, -105, -105, - -105, 103, 92, 144, -105, -105, -105, -105, 125, -105, - 154, 162, 83, 84, -105, 88, 82, 81, 75, 66, - 122, -105, 116, 98, 104, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, 106, -105, 113, -105, - 86, 80, 52, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, 34, -105, - -105, -105, -105, -105, 38, -105, -105, 43, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, 136, -105, 91, -29, -105, -105, 3, -105, 225, - 37, 71, -105, -105, -105, -105, -105, -105, -105, -105, - -3, -105, -105, -105, 18, -105, -105, 27, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, 87, -105, -105, 62, -105, 56, -105, - 50, -105, 31, -105, -105, -105, -105, 59, -105, -105, - -105, 47, 69, -105, -105, -105, -105, -105, 67, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, 30, - -105, -105, -105, -105, 96, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, 10, 184, - -105, 222, 226, 232, 202, -105, 124, 114, 112, 110, - 95, -105, -105, -105, -105, -105, -105, -105, -105, 212, - -105, 192, -105, 177, -105, -105, 208, -105, 107, -105, - -105, 255, -105, 11, -105, 13, -105, 44, -105, 206, - -105, 169, 176, -105, -105, 183, -105, -105, -105, -105, - -105, -105, 173, -105, 167, 117, -105, -105, 191, -105, - 54, -105, 55, -105, 58, -105, -105, 102, -105, -105, - 89, -105, -105, 57, -105, 46, -105, 45, -105, 49, - -105, -105, -105, -105, -105, -105, 77, -105, 64, -105, - 51, -105, 109, 61, -105, -105, 48, -105, -105, 152, - -105, -105, -105, 79, -105, -105, -105, -105, 4, -105, - -16, 153, -105, 74, -105, -105, -11, -105, 0, -105, - -105, -105, -105, -105, -105, -105, -5, -105, -105, -105, - -105, -105, -105, 68, -105, -105, 41, -105, -105, -105, - -105, 90, -105, -1, -105, -105, -105, -105, -105, -93, - -105, 32, -105, -4, -105, -105, -105, -105, -22, -105, - -105, -14, -105, -105, -105, -105, -105, -105, -26, -105, - -105, -2, -105, 60, -105, 53, -105, -105, -105, -105, - 65, -105, 76, -105, 78, -105, 72, -105, -105, -105, - -105, -105, -105, 21, -105, -105, 85, -105, -105, -105, - -105, 22, -105, -105, 180, -105, -105, 33, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, 73, -105, -105, -105, - -105, -105, -105, -105, 63, -105, -105, -105, -105, -105, - -105, 12, -105, -105, -105, -105, -105, -105, -105, -12, - -105, -105, -105, -105, -105, -105, -105, 6, -105, -105, - -105, -105, -15, -105, -105, 9, -105, -105, -105, -105, - -105, -9, -105, -105, -105, -7, -18, -13, -105, -105, - -105, -105, -105, 277, 266, -105, -105, -105, -105, -105, - -105, -105, 269, 2, 26, -105, 24, -105, 170, 16, - -105, -105, 19, -105, -105, 182, -105, -105, -105, 35, - -105, -105, -105, -105, 42, -105, 29, 153, -105, 128, - -105, -105, -105, -105, -105, -105, 349, -105, -105, -105, - -105, -105, 274, -105, -105, -105, 14, -105, -105, 15, - 218, -105, -105, -105, 7, -105, -105, -105, -105, -105, - -105, 17, -105, -105, -105, -105, -105, -105, -105, -105, - -105}; + -106, 12, -87, 18, 17, 212, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -53, + -106, -106, -106, -106, -106, -106, -106, -106, -106, 162, + -106, -106, -106, -4, -106, -106, -11, 24, 75, 76, + -106, 83, 55, -106, -106, 157, 158, -106, -106, -106, + -106, -106, 150, -106, 172, 176, -106, 168, 167, -106, + -106, -106, -106, 173, 154, 115, -106, -106, -106, -106, + 147, -106, 121, 113, 112, 125, -106, 128, 143, 146, + 140, 139, 136, -106, 122, 138, 130, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, 149, -106, + 153, -106, 110, 82, 46, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + 35, -106, -106, -106, -106, -106, 37, -106, -106, 45, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, 92, -106, 88, 58, -106, -106, 51, + -106, 209, 72, 78, -106, -106, -106, -106, -106, -106, + -106, -106, 27, -106, -106, -106, 63, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, 50, -106, -106, 28, -106, + 29, -106, 47, -106, 33, -106, -106, 66, -106, 73, + -106, -106, -106, 81, 53, -106, -106, -106, -106, -106, + -13, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, 9, -106, -106, -106, -106, 111, -106, -106, -106, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + 3, 186, -106, 220, 228, 234, 204, -106, 90, 91, + 94, 97, 93, -106, -106, -106, -106, -106, -106, -106, + -106, 210, -106, 187, -106, 214, -106, -106, 208, -106, + 207, -106, -106, 155, -106, 8, -106, 4, -106, -1, + -106, 217, -106, 177, 185, -106, -106, 184, -106, -106, + -106, -106, -106, -106, 183, -106, 194, 105, -106, -106, + 99, -106, 71, -106, 74, -106, 65, -106, -106, 114, + -106, -106, -55, -106, -106, 64, -106, 44, -106, 30, + -106, 31, -106, -106, -106, -106, -106, -106, 57, -106, + 36, -106, 40, -106, 70, 59, -106, -106, 42, -106, + -106, 104, -106, -106, -106, 38, -106, -106, -106, -106, + 79, -106, 69, 108, -106, 84, -106, -106, 56, -106, + 68, -106, -106, -106, -106, -106, -106, -106, 52, -106, + -106, -106, -106, -106, -106, 109, -106, -106, 77, -106, + -106, -106, -106, 86, -106, 80, -106, -106, -106, -106, + -106, -59, -106, 43, -106, -63, -106, -106, -106, -106, + 98, -106, -106, 95, -106, -106, -106, -106, -106, 60, + -34, -106, -106, 32, -106, 41, -106, 39, -106, -106, + -106, -106, 49, -106, 61, -106, 62, -106, 48, -106, + -106, -106, -106, -106, -106, 23, -106, -106, 96, -106, + -106, -106, -106, 34, -106, -106, 133, -106, -106, 54, + -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, 67, -106, -106, -106, -106, + -106, 22, -106, -106, -106, -106, -106, -106, -106, -22, + -106, -106, -106, -106, -106, -106, 2, -106, -106, -106, + -106, -106, -106, -106, -19, -106, -106, -106, -106, -106, + -106, -106, 100, -106, -106, -106, -106, -21, -106, -106, + -3, -106, -106, -106, -106, -106, 13, -106, -106, -106, + 11, 14, 10, -106, -106, -106, -106, -106, 279, 283, + -106, -106, -106, -106, -106, -106, 19, 273, 15, 16, + -106, 21, -106, 224, 6, -106, -106, 25, -106, -106, + 85, -106, -106, -106, 26, -106, -106, -106, -106, 20, + -106, 7, 87, -106, 107, -106, -106, -106, -106, -106, + -106, 317, -106, -106, -106, -106, -106, 277, -106, -106, + -106, 0, -106, -106, -2, 271, -106, -106, -106, 1, + -106, -106, -106, -106, -106, -106, 5, -106, -106, -106, + -106, -106, -106, -106, -106, -106}; -const int QmlJSGrammar::action_info [] = { - 345, -114, -106, -92, 343, 345, -95, 254, -122, 450, - 549, 187, 437, 413, -119, -117, -106, 454, 249, -92, - 248, 345, 454, 339, 340, 342, 349, 233, 98, 606, - -125, 398, 388, 386, 254, 396, 254, 96, 441, 144, - 98, 450, 167, 161, 138, 606, 437, 443, 554, 463, - 96, 630, 437, 68, 437, 546, 180, 406, 337, 427, - 161, 184, -96, 445, 428, 421, 176, 421, 421, 413, - 417, 411, 525, 322, 186, 454, 146, 405, 289, 535, - 400, 450, 309, 309, 315, -96, -122, 437, 269, -117, - 298, 138, 293, -119, 509, 413, -114, 521, 519, 301, - 532, 554, 68, 328, 330, 269, 291, -95, 303, 424, - 138, 55, 504, 138, 539, 289, 474, 522, 440, 0, - 534, 332, 56, 431, 138, 163, 169, 524, 523, 164, - 620, 619, 441, 138, 324, 239, 238, 246, 245, 59, - 138, 138, 311, 553, 169, 170, 312, 138, 138, 138, - 60, 138, 0, -125, 425, 626, 625, 596, 174, 410, - 409, 55, 55, 170, 475, 415, 138, 246, 245, 554, - 253, 252, 56, 56, 551, 550, 246, 245, 244, 243, - 138, 82, 466, 83, 55, 485, 505, 325, 138, 82, - 0, 83, 452, 334, 84, 56, 82, 100, 83, 456, - 251, 347, 84, 307, 82, 597, 83, 505, 169, 84, - 505, 511, 61, 517, 505, 138, 101, 84, 102, 531, - 530, 527, 0, 541, 138, 0, 169, 170, 0, 403, - 0, 0, 507, 538, 537, 467, 465, 82, 61, 83, - 61, 435, 434, 506, 138, 170, 0, 403, 542, 540, - 84, 623, 622, 507, 505, 0, 507, 62, 32, 507, - 507, 169, 0, 63, 506, 512, 510, 506, 515, 514, - 506, 506, 0, 0, 0, 528, 526, 232, 231, 32, - 170, 621, 171, 62, 32, 62, 169, 616, 32, 63, - 0, 63, 139, 0, 169, 45, 47, 46, 0, 0, - 507, 617, 615, 32, -83, 170, 0, 171, 0, 0, - 0, 506, -83, 170, 32, 171, 45, 47, 46, 32, - 0, 45, 47, 46, 32, 45, 47, 46, 32, 0, - 0, 614, 271, 272, 82, 32, 83, 0, 0, 0, - 45, 47, 46, 4, 3, 2, 1, 84, 271, 272, - 32, 45, 47, 46, 32, 0, 45, 47, 46, 273, - 274, 45, 47, 46, 32, 45, 47, 46, 0, 276, - 277, 0, 45, 47, 46, 273, 274, 32, 278, 0, - 0, 279, 0, 280, 0, 0, 0, 45, 47, 46, - 32, 45, 47, 46, 0, 0, 0, -336, 0, 32, - 0, 45, 47, 46, 0, 0, -336, 70, 71, 276, - 277, 0, 0, 0, 45, 47, 46, 0, 278, 0, - 0, 279, 0, 280, 0, 0, 0, 45, 47, 46, - 0, 75, 76, 0, 72, 73, 45, 47, 46, 77, - 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, - 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, - 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, - 78, 75, 76, 79, 32, 80, 0, 0, 0, 77, - 78, 0, 32, 79, 0, 80, 0, 276, 277, 0, - 32, 0, 0, 0, 0, 0, 278, 0, 32, 279, - 0, 280, 0, 0, 0, 0, 242, 241, 0, 0, - 0, 45, 47, 46, 237, 236, 0, 0, 0, 45, - 47, 46, 237, 236, 0, 0, 0, 45, 47, 46, - 237, 236, 148, 0, 0, 45, 47, 46, 0, 0, - 0, 0, 149, 0, 0, 0, 150, 0, 0, 0, - 0, 0, 0, 0, 0, 151, 0, 152, 0, 0, - 0, 0, 32, 0, 0, 0, 0, 0, 153, 0, - 154, 59, 0, 0, 0, 0, 0, 0, 155, 0, - 0, 156, 60, 0, 0, 0, 0, 157, 148, 0, - 0, 0, 0, 158, 242, 241, 0, 0, 149, 45, - 47, 46, 150, 0, 0, 0, 0, 0, 0, 159, - 0, 151, 0, 152, 0, 0, 305, 0, 0, 0, - 0, 0, 0, 0, 153, 0, 154, 59, 0, 28, - 29, 148, 0, 0, 155, 0, 0, 156, 60, 31, - 0, 149, 0, 157, 0, 150, 32, 0, 0, 158, - 33, 34, 0, 35, 151, 0, 152, 0, 0, 0, - 496, 0, 0, 0, 42, 159, 0, 153, 0, 154, - 59, 0, 0, 0, 0, 0, 0, 155, 0, 0, - 156, 60, 48, 45, 47, 46, 157, 49, 0, 0, - 0, 0, 158, 0, 0, 0, 0, 0, 41, 51, - 30, 0, 0, 0, 38, 0, 0, 0, 159, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, - 0, 0, 0, 0, 0, 0, 28, 29, 31, 0, - 0, 0, 0, 0, 0, 32, 31, 0, 0, 33, - 34, 0, 35, 32, 0, 0, 0, 33, 34, 39, - 35, 0, 0, 42, 0, 0, 0, 496, 0, 0, - 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 45, 47, 46, 0, 49, 0, 0, 48, - 45, 47, 46, 0, 49, 0, 0, 41, 51, 30, - 0, 0, 0, 38, 0, 41, 51, 30, 0, 0, - 0, 38, 0, 0, 28, 29, 0, 0, 0, 0, - 0, 0, 28, 29, 31, 0, 0, 0, 0, 0, - 0, 32, 31, 0, 0, 33, 34, 0, 35, 32, - 0, 0, 0, 33, 34, 496, 35, 0, 0, 42, - 0, 0, 0, 39, 0, 0, 0, 42, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, - 46, 0, 49, 0, 0, 48, 45, 47, 46, 0, - 49, 0, 0, 41, 51, 30, 0, 0, 0, 38, - 0, 41, 51, 30, 0, 0, 0, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, - 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, - 0, 0, 0, 0, 0, 32, 0, 0, 0, 33, - 34, 0, 35, 0, 0, 0, 0, 0, 0, 496, - 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, +const short QmlJSGrammar::action_info [] = { + -97, -98, 452, 611, -116, 527, 456, -124, 415, -121, + 439, 551, -119, -108, 347, -94, 611, 388, 635, 540, + 351, 341, 344, 342, 390, 539, -127, 256, 398, 402, + 100, 98, 70, -97, 400, 163, -98, 465, 524, -116, + 559, 447, 530, -108, 439, -127, 509, 439, 559, -94, + 537, 544, -121, 256, 443, -119, -124, 514, 439, 347, + 445, 526, 423, 452, 423, 430, 456, 423, 70, 554, + 169, 415, 345, 311, 100, 163, 419, 140, 146, 408, + 271, 413, 347, 251, 295, 271, 256, 0, 186, 452, + 0, 311, 456, 140, 429, 317, 0, 0, 0, 324, + 407, 178, 291, 98, 305, 558, 0, 235, 476, 0, + 439, 415, 300, 442, 291, 0, 189, 171, 140, 426, + 140, 148, 339, 182, 433, 140, 140, 443, 140, 303, + 326, 559, 140, 0, 140, 57, 172, 250, 188, 140, + 601, 140, 330, 293, 165, 0, 58, 313, 166, 140, + 332, 314, 631, 630, 255, 254, 477, 241, 240, 57, + 246, 245, 412, 411, 427, 57, 141, 529, 528, 63, + 58, 61, 336, 171, 248, 247, 58, 516, 253, 0, + 417, 468, 62, 327, 309, 334, 458, 57, 602, 248, + 247, 487, 172, 454, 522, 556, 555, 176, 58, 248, + 247, 625, 624, 84, 84, 85, 85, 140, 84, 84, + 85, 85, 63, 84, 64, 85, 86, 86, 510, 510, + 65, 86, 86, 84, 171, 85, 86, 63, 84, 0, + 85, 517, 515, 140, 469, 467, 86, 84, 140, 85, + 512, 86, 84, 172, 85, 405, 84, 102, 85, 140, + 86, 511, 628, 627, 140, 86, 84, 64, 85, 86, + 437, 436, 171, 65, 512, 512, 103, 510, 104, 86, + 546, 510, 64, 140, 510, 511, 511, 84, 65, 85, + 532, 172, 626, 405, 34, 0, 234, 233, 0, 0, + 86, 520, 519, 0, 0, 547, 545, 84, 0, 85, + 621, 0, 543, 542, 34, 0, 349, 0, 0, 0, + 86, 72, 73, 512, 622, 620, 34, 512, 0, 34, + 512, 47, 49, 48, 511, 0, 536, 535, 511, 171, + 0, 511, 34, 0, 533, 531, 72, 73, 74, 75, + 34, 47, 49, 48, 619, 34, 171, -85, 172, 34, + 173, 0, 34, 47, 49, 48, 47, 49, 48, 34, + 0, 0, 34, 74, 75, 172, 34, 173, 0, 47, + 49, 48, 34, 0, 171, 34, 0, 47, 49, 48, + 0, 0, 47, 49, 48, 0, 47, 49, 48, 47, + 49, 48, -85, 172, 0, 173, 47, 49, 48, 47, + 49, 48, 0, 47, 49, 48, 278, 279, 0, 47, + 49, 48, 47, 49, 48, 280, 278, 279, 281, 0, + 282, 0, 0, 34, 0, 280, 34, 0, 281, 34, + 282, 273, 274, -339, 278, 279, -339, 34, 0, 0, + 0, 0, 0, 280, 0, 0, 281, 0, 282, 34, + 0, 0, 0, 0, 0, 244, 243, 0, 275, 276, + 47, 49, 48, 47, 49, 48, 47, 49, 48, 244, + 243, 77, 78, 34, 47, 49, 48, 0, 0, 79, + 80, 239, 238, 81, 0, 82, 47, 49, 48, 77, + 78, 34, 0, 0, 0, 0, 0, 79, 80, 0, + 0, 81, 0, 82, 0, 239, 238, 77, 78, 34, + 47, 49, 48, 278, 279, 79, 80, 0, 0, 81, + 0, 82, 280, 244, 243, 281, 0, 282, 47, 49, + 48, 6, 5, 4, 1, 3, 2, 0, 0, 150, + 0, 239, 238, 0, 0, 0, 47, 49, 48, 151, + 0, 0, 0, 152, 0, 0, 0, 150, 0, 0, + 0, 0, 153, 0, 154, 0, 0, 151, 0, 0, + 0, 152, 0, 0, 0, 155, 0, 156, 61, 0, + 153, 0, 154, 0, 0, 157, 0, 0, 158, 62, + 77, 78, 0, 155, 159, 156, 61, 0, 79, 80, + 160, 0, 81, 157, 82, 0, 158, 62, 0, 0, + 0, 0, 159, 0, 0, 0, 161, 0, 160, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, + 31, 0, 0, 0, 161, 0, 0, 0, 0, 33, + 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, + 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, + 501, 0, 0, 0, 44, 0, 0, 150, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, + 0, 152, 50, 47, 49, 48, 0, 51, 0, 0, + 153, 0, 154, 0, 0, 307, 0, 0, 43, 53, + 32, 0, 0, 155, 40, 156, 61, 0, 0, 0, + 0, 0, 0, 157, 0, 0, 158, 62, 0, 0, + 0, 0, 159, 0, 0, 0, 0, 0, 160, 0, + 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, + 0, 0, 0, 0, 161, 0, 33, 0, 0, 0, + 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, + 37, 0, 0, 0, 30, 31, 0, 41, 0, 0, + 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 50, + 47, 49, 48, 0, 51, 501, 0, 0, 0, 44, + 0, 0, 0, 0, 0, 43, 53, 32, 0, 0, + 0, 40, 0, 0, 0, 0, 0, 50, 47, 49, + 48, 0, 51, 0, 500, 0, 30, 31, 0, 0, + 0, 0, 0, 43, 53, 32, 214, 0, 0, 40, + 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, + 37, 0, 30, 31, 0, 0, 0, 501, 0, 0, + 0, 44, 33, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 0, 0, 50, + 502, 504, 503, 41, 51, 0, 0, 44, 0, 225, + 0, 0, 0, 0, 0, 43, 53, 32, 209, 0, + 0, 40, 0, 0, 0, 50, 47, 49, 48, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 45, 47, 46, 0, 49, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 41, 51, 30, - 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 495, 0, 28, 29, 0, 0, - 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, - 0, 0, 0, 32, 0, 0, 0, 33, 34, 0, - 35, 0, 0, 0, 0, 0, 0, 496, 0, 0, - 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 497, 499, 498, 0, 49, 0, 0, 0, 0, 223, - 0, 0, 0, 0, 0, 41, 51, 30, 207, 0, - 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 495, 0, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, - 0, 0, 0, 0, 0, 496, 0, 0, 0, 42, - 0, 0, 0, 0, 0, 0, 0, 600, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 497, 499, - 498, 0, 49, 0, 0, 0, 0, 223, 0, 0, - 0, 0, 0, 41, 51, 30, 207, 0, 0, 38, + 500, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 214, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, + 0, 0, 0, 501, 0, 0, 0, 44, 0, 0, + 0, 0, 0, 0, 0, 608, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 502, 504, 503, 0, + 51, 0, 0, 0, 0, 225, 0, 0, 0, 0, + 0, 43, 53, 32, 209, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 495, 0, 28, 29, 0, 0, 0, 0, 0, 0, - 0, 0, 212, 0, 0, 0, 0, 0, 0, 32, - 0, 0, 0, 33, 34, 0, 35, 0, 0, 0, - 0, 0, 0, 496, 0, 0, 0, 42, 0, 0, - 0, 0, 0, 0, 0, 603, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48, 497, 499, 498, 0, - 49, 0, 0, 0, 0, 223, 0, 0, 0, 0, - 0, 41, 51, 30, 207, 0, 0, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, - 29, 0, 0, 0, 0, 0, 0, 0, 0, 31, - 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, - 33, 34, 0, 35, 0, 0, 0, 36, 0, 37, - 39, 40, 0, 0, 42, 0, 0, 0, 43, 0, - 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 48, 45, 47, 46, 0, 49, 0, 50, - 0, 52, 0, 53, 0, 0, 0, 0, 41, 51, - 30, 0, 0, 0, 38, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, - 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, - 0, 0, 0, 32, 0, 0, 0, 33, 34, 0, - 35, 0, 0, 0, 36, 0, 37, 39, 40, 0, - 0, 42, 0, 0, 0, 43, 0, 44, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 45, 47, 46, 0, 49, 0, 50, 0, 52, 268, - 53, 0, 0, 0, 0, 41, 51, 30, 0, 0, - 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -115, 0, 0, 0, 27, 28, 29, 0, - 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 33, 34, - 0, 35, 0, 0, 0, 36, 0, 37, 39, 40, - 0, 0, 42, 0, 0, 0, 43, 0, 44, 0, + 500, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 214, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, + 0, 0, 0, 501, 0, 0, 0, 44, 0, 0, + 0, 0, 0, 0, 0, 605, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 502, 504, 503, 0, + 51, 0, 0, 0, 0, 225, 0, 0, 0, 0, + 0, 43, 53, 32, 209, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 45, 47, 46, 0, 49, 0, 50, 0, 52, - 0, 53, 0, 0, 0, 0, 41, 51, 30, 0, - 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 480, 0, 0, 27, 28, 29, 0, - 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 33, 34, - 0, 35, 0, 0, 0, 36, 0, 37, 39, 40, - 0, 0, 42, 0, 0, 0, 43, 0, 44, 0, - 0, 481, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 45, 47, 46, 0, 49, 0, 50, 0, 52, - 0, 53, 0, 0, 0, 0, 41, 51, 30, 0, - 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 27, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 0, 32, 214, 0, 0, 561, 562, 0, 35, 0, - 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, - 0, 0, 0, 43, 0, 44, 0, 0, 0, 0, - 0, 0, 0, 218, 0, 0, 0, 48, 45, 47, - 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, - 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, + 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, + 45, 0, 46, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 47, 49, 48, 0, 51, + 0, 52, 0, 54, 0, 55, 0, 0, 0, 0, + 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, + 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, + 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, + 0, 0, 0, 45, 0, 46, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 47, 49, + 48, 0, 51, 0, 52, 0, 54, 0, 55, 0, + 0, 0, 0, 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 480, 0, 0, 27, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, - 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, - 0, 0, 0, 43, 0, 44, 0, 0, 483, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, - 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, - 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, + 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, + 0, 0, 45, 0, 46, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 47, 49, 48, + 0, 51, 0, 52, 0, 54, 270, 55, 0, 0, + 0, 0, 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 472, 0, 0, 27, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, - 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, - 0, 0, 0, 43, 0, 44, 0, 0, 473, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, - 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, - 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, + 216, 0, 0, 566, 567, 0, 37, 0, 0, 0, + 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, + 0, 45, 0, 46, 0, 0, 0, 0, 0, 0, + 0, 220, 0, 0, 0, 50, 47, 49, 48, 0, + 51, 0, 52, 0, 54, 0, 55, 0, 0, 0, + 0, 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 472, 0, 0, 27, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, - 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, - 0, 0, 0, 43, 0, 44, 0, 0, 478, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, - 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, - 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 474, 0, 0, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, + 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, + 0, 0, 0, 45, 0, 46, 0, 0, 475, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 47, 49, + 48, 0, 51, 0, 52, 0, 54, 0, 55, 0, + 0, 0, 0, 43, 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 106, 107, 108, 0, 0, 110, 112, 113, 0, 0, - 114, 0, 115, 0, 0, 0, 117, 118, 119, 0, - 0, 0, 0, 0, 0, 32, 120, 121, 122, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, + 0, 0, 474, 0, 0, 29, 30, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, + 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, + 0, 44, 0, 0, 0, 45, 0, 46, 0, 0, + 480, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 47, 49, 48, 0, 51, 0, 52, 0, 54, 0, + 55, 0, 0, 0, 0, 43, 53, 32, 0, 0, + 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 482, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, + 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, + 42, 0, 0, 44, 0, 0, 0, 45, 0, 46, + 0, 0, 485, 0, 0, 0, 0, 0, 0, 0, + 0, 50, 47, 49, 48, 0, 51, 0, 52, 0, + 54, 0, 55, 0, 0, 0, 0, 43, 53, 32, + 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 482, 0, 0, 29, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, + 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, + 39, 41, 42, 0, 0, 44, 0, 0, 0, 45, + 0, 46, 0, 0, 483, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 47, 49, 48, 0, 51, 0, + 52, 0, 54, 0, 55, 0, 0, 0, 0, 43, + 53, 32, 0, 0, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 108, 109, + 110, 0, 0, 112, 114, 115, 0, 0, 116, 0, + 117, 0, 0, 0, 119, 120, 121, 0, 0, 0, + 0, 0, 0, 34, 122, 123, 124, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, - 0, 0, 45, 47, 46, 127, 128, 129, 0, 131, - 132, 133, 134, 135, 136, 0, 0, 124, 130, 116, - 109, 111, 125, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 106, 107, 108, 0, 0, 110, - 112, 113, 0, 0, 114, 0, 115, 0, 0, 0, - 117, 118, 119, 0, 0, 0, 0, 0, 0, 390, - 120, 121, 122, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 123, 0, 0, 0, 391, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, - 0, 0, 0, 0, 0, 395, 392, 394, 0, 127, - 128, 129, 0, 131, 132, 133, 134, 135, 136, 0, - 0, 124, 130, 116, 109, 111, 125, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 106, 107, - 108, 0, 0, 110, 112, 113, 0, 0, 114, 0, - 115, 0, 0, 0, 117, 118, 119, 0, 0, 0, - 0, 0, 0, 390, 120, 121, 122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, - 0, 391, 0, 0, 0, 0, 0, 0, 0, 393, - 0, 0, 0, 126, 0, 0, 0, 0, 0, 395, - 392, 394, 0, 127, 128, 129, 0, 131, 132, 133, - 134, 135, 136, 0, 0, 124, 130, 116, 109, 111, - 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 206, 0, 0, 0, 0, 208, 0, 27, - 28, 29, 210, 0, 0, 0, 0, 0, 0, 211, - 31, 0, 0, 0, 0, 0, 0, 213, 214, 0, - 0, 215, 34, 0, 35, 0, 0, 0, 36, 0, - 37, 39, 40, 0, 0, 42, 0, 0, 0, 43, - 0, 44, 0, 0, 0, 0, 0, 217, 0, 218, - 0, 0, 0, 48, 216, 219, 46, 220, 49, 221, - 50, 222, 52, 223, 53, 224, 225, 0, 0, 41, - 51, 30, 207, 209, 0, 38, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, - 0, 208, 0, 27, 28, 29, 210, 0, 0, 0, - 0, 0, 0, 211, 212, 0, 0, 0, 0, 0, - 0, 213, 214, 0, 0, 215, 34, 0, 35, 0, - 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, - 0, 0, 0, 43, 0, 44, 0, 0, 0, 0, - 0, 217, 0, 218, 0, 0, 0, 48, 216, 219, - 46, 220, 49, 221, 50, 222, 52, 223, 53, 224, - 225, 0, 0, 41, 51, 30, 207, 209, 0, 38, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 564, 107, 108, 0, 0, 566, 112, 568, 28, 29, - 569, 0, 115, 0, 0, 0, 117, 571, 572, 0, - 0, 0, 0, 0, 0, 573, 574, 121, 122, 215, - 34, 0, 35, 0, 0, 0, 36, 0, 37, 575, - 40, 0, 0, 577, 0, 0, 0, 43, 0, 44, - 0, 0, 0, 0, 0, 579, 0, 218, 0, 0, - 0, 581, 578, 580, 46, 582, 583, 584, 50, 586, - 587, 588, 589, 590, 591, 0, 0, 576, 585, 570, - 565, 567, 125, 38, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 358, 107, 108, 0, 0, 360, - 112, 362, 28, 29, 363, 0, 115, 0, 0, 0, - 117, 365, 366, 0, 0, 0, 0, 0, 0, 367, - 368, 121, 122, 215, 34, 0, 35, 0, 0, 0, - 36, 0, 37, 369, 40, 0, 0, 371, 0, 0, - 0, 43, 0, 44, 0, -261, 0, 0, 0, 373, - 0, 218, 0, 0, 0, 375, 372, 374, 46, 376, - 377, 378, 50, 380, 381, 382, 383, 384, 385, 0, - 0, 370, 379, 364, 359, 361, 125, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 548, 422, 414, 436, 166, 547, 552, 433, 533, 529, - 183, 520, 536, 304, 545, 513, 306, 447, 247, 599, - 618, 147, 387, 317, 627, 613, 14, 492, 397, 204, - 624, 185, 179, 250, 389, 430, 168, 240, 299, 235, - 173, 179, 484, 407, 336, 433, 308, 348, 436, 346, - 433, 350, 247, 469, 464, 482, 331, 429, 333, 344, - 335, 179, 299, 247, 240, 432, 479, 140, 451, 240, - 442, 145, 446, 444, 457, 235, 160, 235, 453, 399, - 458, 455, 299, 137, 516, 143, 508, 426, 436, 204, - 0, 204, 412, 0, 0, 0, 0, 0, 458, 103, - 0, 143, 0, 0, 143, 0, 404, 0, 57, 175, - 299, 0, 57, 91, 177, 183, 57, 57, 449, 0, - 299, 105, 90, 57, 57, 57, 57, 0, 89, 88, - 57, 94, 95, 57, 57, 81, 65, 57, 263, 57, - 57, 486, 285, 267, 86, 57, 57, 64, 57, 165, - 87, 57, 57, 177, 57, 57, 57, 284, 57, 283, - 97, 282, 85, 401, 57, 99, 57, 57, 468, 92, - 57, 281, 449, 300, 57, 69, 491, 57, 57, 449, - 317, 57, 57, 327, 58, 67, 57, 341, 66, 401, - 234, 402, 162, 401, 299, 57, 57, 448, 57, 338, - 489, 57, 74, 488, 57, 57, 57, 487, 490, 477, - 93, 57, 57, 476, 177, 295, 267, 402, 295, 295, - 267, 402, 0, 267, 267, 295, 57, 494, 313, 494, - 267, 267, 628, 0, 57, 270, 595, 323, 103, 267, - 314, 294, 493, 503, 57, 292, 0, 316, 57, 267, - 295, 288, 326, 267, 57, 267, 0, 329, 299, 267, - 105, 172, 0, 310, 57, 0, 0, 290, 57, 267, - 601, 275, 297, 267, 57, 286, 0, 494, 604, 267, - 592, 287, 0, 594, 0, 494, 0, 595, 560, 0, - 0, 0, 493, 503, 0, 563, 556, 557, 558, 559, - 493, 503, 469, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, + 47, 49, 48, 129, 130, 131, 0, 133, 134, 135, + 136, 137, 138, 0, 0, 126, 132, 118, 111, 113, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 108, 109, 110, 0, 0, 112, + 114, 115, 0, 0, 116, 0, 117, 0, 0, 0, + 119, 120, 121, 0, 0, 0, 0, 0, 0, 392, + 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 125, 0, 0, 0, 393, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 397, 394, 396, 0, 129, + 130, 131, 0, 133, 134, 135, 136, 137, 138, 0, + 0, 126, 132, 118, 111, 113, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 302, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 109, 110, 0, 0, 112, 114, 115, 0, 0, + 116, 0, 117, 0, 0, 0, 119, 120, 121, 0, + 0, 0, 0, 0, 0, 392, 122, 123, 124, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, + 0, 0, 0, 393, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 0, 128, 0, 0, 0, 0, + 0, 397, 394, 396, 0, 129, 130, 131, 0, 133, + 134, 135, 136, 137, 138, 0, 0, 126, 132, 118, + 111, 113, 127, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, + 0, 210, 0, 29, 30, 31, 212, 0, 0, 0, + 0, 0, 0, 213, 33, 0, 0, 0, 0, 0, + 0, 215, 216, 0, 0, 217, 36, 0, 37, 0, + 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, + 0, 0, 0, 45, 0, 46, 0, 0, 0, 0, + 0, 219, 0, 220, 0, 0, 0, 50, 218, 221, + 48, 222, 51, 223, 52, 224, 54, 225, 55, 226, + 227, 0, 0, 43, 53, 32, 209, 211, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 208, 0, 0, 0, 0, 210, 0, 29, + 30, 31, 212, 0, 0, 0, 0, 0, 0, 213, + 214, 0, 0, 0, 0, 0, 0, 215, 216, 0, + 0, 217, 36, 0, 37, 0, 0, 0, 38, 0, + 39, 41, 42, 0, 0, 44, 0, 0, 0, 45, + 0, 46, 0, 0, 0, 0, 0, 219, 0, 220, + 0, 0, 0, 50, 218, 221, 48, 222, 51, 223, + 52, 224, 54, 225, 55, 226, 227, 0, 0, 43, + 53, 32, 209, 211, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 569, 109, + 110, 0, 0, 571, 114, 573, 30, 31, 574, 0, + 117, 0, 0, 0, 119, 576, 577, 0, 0, 0, + 0, 0, 0, 578, 579, 123, 124, 217, 36, 0, + 37, 0, 0, 0, 38, 0, 39, 580, 42, 0, + 0, 582, 0, 0, 0, 45, 0, 46, 0, 0, + 0, 0, 0, 584, 0, 220, 0, 0, 0, 586, + 583, 585, 48, 587, 588, 589, 52, 591, 592, 593, + 594, 595, 596, 0, 0, 581, 590, 575, 570, 572, + 127, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 360, 109, 110, 0, 0, 362, + 114, 364, 30, 31, 365, 0, 117, 0, 0, 0, + 119, 367, 368, 0, 0, 0, 0, 0, 0, 369, + 370, 123, 124, 217, 36, 0, 37, 0, 0, 0, + 38, 0, 39, 371, 42, 0, 0, 373, 0, 0, + 0, 45, 0, 46, 0, -263, 0, 0, 0, 375, + 0, 220, 0, 0, 0, 377, 374, 376, 48, 378, + 379, 380, 52, 382, 383, 384, 385, 386, 387, 0, + 0, 372, 381, 366, 361, 363, 127, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 541, 310, 460, 513, 538, 518, 525, 308, 249, 632, + 306, 181, 252, 618, 149, 16, 623, 495, 319, 497, + 629, 357, 496, 435, 471, 553, 557, 486, 438, 301, + 428, 237, 350, 352, 604, 521, 242, 424, 550, 552, + 181, 301, 185, 237, 242, 343, 432, 348, 338, 249, + 459, 237, 453, 449, 236, 242, 446, 181, 466, 401, + 448, 249, 357, 455, 444, 457, 346, 337, 357, 484, + 142, 236, 147, 333, 438, 175, 301, 335, 187, 409, + 162, 145, 435, 416, 435, 139, 170, 399, 414, 481, + 438, 389, 0, 168, 0, 0, 403, 357, 403, 59, + 357, 490, 301, 534, 391, 0, 0, 0, 301, 0, + 0, 460, 0, 145, 59, 0, 179, 403, 177, 59, + 59, 488, 489, 0, 404, 105, 404, 0, 59, 185, + 451, 59, 59, 450, 59, 59, 59, 59, 59, 283, + 284, 59, 287, 285, 145, 404, 286, 107, 167, 406, + 164, 59, 59, 451, 450, 265, 59, 59, 301, 59, + 269, 68, 96, 95, 479, 59, 59, 331, 478, 59, + 87, 76, 59, 329, 59, 97, 434, 83, 89, 431, + 59, 470, 59, 59, 59, 94, 88, 59, 93, 92, + 59, 59, 90, 59, 59, 91, 493, 59, 59, 71, + 67, 59, 59, 491, 492, 99, 59, 101, 179, 319, + 301, 59, 59, 340, 69, 60, 59, 59, 450, 66, + 59, 59, 451, 304, 105, 499, 269, 297, 297, 297, + 59, 59, 269, 269, 269, 269, 269, 0, 315, 272, + 498, 508, 294, 0, 0, 0, 107, 174, 59, 325, + 318, 316, 297, 269, 59, 290, 0, 269, 297, 269, + 0, 59, 0, 269, 59, 0, 269, 292, 59, 269, + 179, 277, 59, 0, 299, 302, 312, 269, 59, 288, + 296, 328, 609, 269, 499, 289, 597, 633, 606, 599, + 499, 600, 565, 600, 0, 0, 499, 0, 0, 568, + 561, 562, 563, 564, 0, 498, 508, 0, 471, 0, + 0, 498, 508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 494, 0, 0, 598, 0, 0, 0, 595, 0, 0, + 499, 0, 0, 603, 0, 0, 0, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -645,124 +636,102 @@ const int QmlJSGrammar::action_info [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0}; + 0, 0, 0}; -const int QmlJSGrammar::action_check [] = { - 36, 7, 7, 7, 7, 36, 7, 36, 7, 36, - 60, 33, 33, 36, 7, 7, 7, 36, 36, 7, - 77, 36, 36, 60, 33, 55, 16, 55, 79, 90, - 7, 55, 8, 7, 36, 7, 36, 48, 20, 8, - 79, 36, 7, 2, 8, 90, 33, 36, 33, 17, - 48, 0, 33, 1, 33, 8, 36, 7, 36, 55, - 2, 8, 7, 60, 7, 5, 60, 5, 5, 36, - 33, 7, 29, 17, 60, 36, 60, 60, 48, 7, - 55, 36, 2, 2, 7, 7, 7, 33, 1, 7, - 61, 8, 8, 7, 29, 36, 7, 24, 37, 61, - 66, 33, 1, 61, 60, 1, 79, 7, 60, 10, - 8, 40, 66, 8, 29, 48, 8, 29, 6, -1, - 29, 31, 51, 7, 8, 50, 15, 61, 62, 54, - 61, 62, 20, 8, 8, 61, 62, 61, 62, 42, - 8, 8, 50, 7, 15, 34, 54, 8, 8, 8, - 53, 8, -1, 7, 55, 61, 62, 8, 56, 61, - 62, 40, 40, 34, 56, 60, 8, 61, 62, 33, - 61, 62, 51, 51, 61, 62, 61, 62, 61, 62, - 8, 25, 8, 27, 40, 60, 29, 61, 8, 25, - -1, 27, 60, 60, 38, 51, 25, 15, 27, 60, - 60, 60, 38, 60, 25, 56, 27, 29, 15, 38, - 29, 7, 12, 29, 29, 8, 34, 38, 36, 61, - 62, 7, -1, 36, 8, -1, 15, 34, -1, 36, - -1, -1, 75, 61, 62, 61, 62, 25, 12, 27, - 12, 61, 62, 86, 8, 34, -1, 36, 61, 62, - 38, 61, 62, 75, 29, -1, 75, 57, 29, 75, - 75, 15, -1, 63, 86, 61, 62, 86, 61, 62, - 86, 86, -1, -1, -1, 61, 62, 61, 62, 29, - 34, 91, 36, 57, 29, 57, 15, 47, 29, 63, - -1, 63, 56, -1, 15, 66, 67, 68, -1, -1, - 75, 61, 62, 29, 33, 34, -1, 36, -1, -1, - -1, 86, 33, 34, 29, 36, 66, 67, 68, 29, - -1, 66, 67, 68, 29, 66, 67, 68, 29, -1, - -1, 91, 18, 19, 25, 29, 27, -1, -1, -1, - 66, 67, 68, 92, 93, 94, 95, 38, 18, 19, - 29, 66, 67, 68, 29, -1, 66, 67, 68, 45, - 46, 66, 67, 68, 29, 66, 67, 68, -1, 23, - 24, -1, 66, 67, 68, 45, 46, 29, 32, -1, - -1, 35, -1, 37, -1, -1, -1, 66, 67, 68, - 29, 66, 67, 68, -1, -1, -1, 36, -1, 29, - -1, 66, 67, 68, -1, -1, 36, 18, 19, 23, - 24, -1, -1, -1, 66, 67, 68, -1, 32, -1, - -1, 35, -1, 37, -1, -1, -1, 66, 67, 68, - -1, 23, 24, -1, 45, 46, 66, 67, 68, 31, - 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, - 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, - 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, - 32, 23, 24, 35, 29, 37, -1, -1, -1, 31, - 32, -1, 29, 35, -1, 37, -1, 23, 24, -1, - 29, -1, -1, -1, -1, -1, 32, -1, 29, 35, - -1, 37, -1, -1, -1, -1, 61, 62, -1, -1, - -1, 66, 67, 68, 61, 62, -1, -1, -1, 66, - 67, 68, 61, 62, -1, -1, -1, 66, 67, 68, - 61, 62, 3, -1, -1, 66, 67, 68, -1, -1, - -1, -1, 13, -1, -1, -1, 17, -1, -1, -1, - -1, -1, -1, -1, -1, 26, -1, 28, -1, -1, - -1, -1, 29, -1, -1, -1, -1, -1, 39, -1, - 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, - -1, 52, 53, -1, -1, -1, -1, 58, 3, -1, - -1, -1, -1, 64, 61, 62, -1, -1, 13, 66, - 67, 68, 17, -1, -1, -1, -1, -1, -1, 80, - -1, 26, -1, 28, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, 41, 42, -1, 12, - 13, 3, -1, -1, 49, -1, -1, 52, 53, 22, - -1, 13, -1, 58, -1, 17, 29, -1, -1, 64, - 33, 34, -1, 36, 26, -1, 28, -1, -1, -1, - 43, -1, -1, -1, 47, 80, -1, 39, -1, 41, - 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, - 52, 53, 65, 66, 67, 68, 58, 70, -1, -1, - -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, -1, 80, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, - -1, -1, -1, -1, -1, -1, 12, 13, 22, -1, - -1, -1, -1, -1, -1, 29, 22, -1, -1, 33, - 34, -1, 36, 29, -1, -1, -1, 33, 34, 43, - 36, -1, -1, 47, -1, -1, -1, 43, -1, -1, - -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, -1, 65, - 66, 67, 68, -1, 70, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, 81, 82, 83, -1, -1, - -1, 87, -1, -1, 12, 13, -1, -1, -1, -1, - -1, -1, 12, 13, 22, -1, -1, -1, -1, -1, - -1, 29, 22, -1, -1, 33, 34, -1, 36, 29, - -1, -1, -1, 33, 34, 43, 36, -1, -1, 47, - -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, -1, 65, 66, 67, 68, -1, - 70, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, - -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, +const short QmlJSGrammar::action_check [] = { + 7, 7, 36, 90, 7, 29, 36, 7, 36, 7, + 33, 8, 7, 7, 36, 7, 90, 7, 0, 7, + 16, 60, 55, 33, 8, 29, 7, 36, 7, 55, + 79, 48, 1, 7, 55, 2, 7, 17, 37, 7, + 33, 60, 29, 7, 33, 7, 66, 33, 33, 7, + 66, 29, 7, 36, 20, 7, 7, 29, 33, 36, + 36, 24, 5, 36, 5, 7, 36, 5, 1, 60, + 7, 36, 7, 2, 79, 2, 33, 8, 8, 7, + 1, 7, 36, 36, 8, 1, 36, -1, 8, 36, + -1, 2, 36, 8, 55, 7, -1, -1, -1, 17, + 60, 60, 48, 48, 60, 7, -1, 55, 8, -1, + 33, 36, 61, 6, 48, -1, 33, 15, 8, 10, + 8, 60, 36, 36, 7, 8, 8, 20, 8, 61, + 8, 33, 8, -1, 8, 40, 34, 77, 60, 8, + 8, 8, 61, 79, 50, -1, 51, 50, 54, 8, + 60, 54, 61, 62, 61, 62, 56, 61, 62, 40, + 61, 62, 61, 62, 55, 40, 56, 61, 62, 12, + 51, 42, 60, 15, 61, 62, 51, 7, 60, -1, + 60, 8, 53, 61, 60, 31, 60, 40, 56, 61, + 62, 60, 34, 60, 29, 61, 62, 56, 51, 61, + 62, 61, 62, 25, 25, 27, 27, 8, 25, 25, + 27, 27, 12, 25, 57, 27, 38, 38, 29, 29, + 63, 38, 38, 25, 15, 27, 38, 12, 25, -1, + 27, 61, 62, 8, 61, 62, 38, 25, 8, 27, + 75, 38, 25, 34, 27, 36, 25, 15, 27, 8, + 38, 86, 61, 62, 8, 38, 25, 57, 27, 38, + 61, 62, 15, 63, 75, 75, 34, 29, 36, 38, + 36, 29, 57, 8, 29, 86, 86, 25, 63, 27, + 7, 34, 91, 36, 29, -1, 61, 62, -1, -1, + 38, 61, 62, -1, -1, 61, 62, 25, -1, 27, + 47, -1, 61, 62, 29, -1, 60, -1, -1, -1, + 38, 18, 19, 75, 61, 62, 29, 75, -1, 29, + 75, 66, 67, 68, 86, -1, 61, 62, 86, 15, + -1, 86, 29, -1, 61, 62, 18, 19, 45, 46, + 29, 66, 67, 68, 91, 29, 15, 33, 34, 29, + 36, -1, 29, 66, 67, 68, 66, 67, 68, 29, + -1, -1, 29, 45, 46, 34, 29, 36, -1, 66, + 67, 68, 29, -1, 15, 29, -1, 66, 67, 68, + -1, -1, 66, 67, 68, -1, 66, 67, 68, 66, + 67, 68, 33, 34, -1, 36, 66, 67, 68, 66, + 67, 68, -1, 66, 67, 68, 23, 24, -1, 66, + 67, 68, 66, 67, 68, 32, 23, 24, 35, -1, + 37, -1, -1, 29, -1, 32, 29, -1, 35, 29, + 37, 18, 19, 36, 23, 24, 36, 29, -1, -1, + -1, -1, -1, 32, -1, -1, 35, -1, 37, 29, + -1, -1, -1, -1, -1, 61, 62, -1, 45, 46, + 66, 67, 68, 66, 67, 68, 66, 67, 68, 61, + 62, 23, 24, 29, 66, 67, 68, -1, -1, 31, + 32, 61, 62, 35, -1, 37, 66, 67, 68, 23, + 24, 29, -1, -1, -1, -1, -1, 31, 32, -1, + -1, 35, -1, 37, -1, 61, 62, 23, 24, 29, + 66, 67, 68, 23, 24, 31, 32, -1, -1, 35, + -1, 37, 32, 61, 62, 35, -1, 37, 66, 67, + 68, 92, 93, 94, 95, 96, 97, -1, -1, 3, + -1, 61, 62, -1, -1, -1, 66, 67, 68, 13, + -1, -1, -1, 17, -1, -1, -1, 3, -1, -1, + -1, -1, 26, -1, 28, -1, -1, 13, -1, -1, + -1, 17, -1, -1, -1, 39, -1, 41, 42, -1, + 26, -1, 28, -1, -1, 49, -1, -1, 52, 53, + 23, 24, -1, 39, 58, 41, 42, -1, 31, 32, + 64, -1, 35, 49, 37, -1, 52, 53, -1, -1, + -1, -1, 58, -1, -1, -1, 80, -1, 64, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, + 13, -1, -1, -1, 80, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 47, -1, -1, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, + -1, 17, 65, 66, 67, 68, -1, 70, -1, -1, + 26, -1, 28, -1, -1, 31, -1, -1, 81, 82, + 83, -1, -1, 39, 87, 41, 42, -1, -1, -1, + -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, + -1, -1, 58, -1, -1, -1, -1, -1, 64, -1, + -1, -1, -1, -1, -1, -1, 12, 13, -1, -1, + -1, -1, -1, -1, 80, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, + -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, + 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, + -1, 87, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 10, -1, 12, 13, -1, -1, + -1, -1, -1, 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, - 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, - -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, - 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, + 36, -1, 12, 13, -1, -1, -1, 43, -1, -1, + -1, 47, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, 65, + 66, 67, 68, 43, 70, -1, -1, 47, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, - -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, - -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, - -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, + -1, 87, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, @@ -772,68 +741,51 @@ const int QmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, - -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, - -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, - -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, - 66, 67, 68, -1, 70, -1, 72, -1, 74, 75, - 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, - -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, - -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, - -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, + 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, + -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, + -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, 72, -1, 74, 75, 76, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, + -1, 61, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, + -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, @@ -844,15 +796,43 @@ const int QmlJSGrammar::action_check [] = { 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, + 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, + -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, + 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, - 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, + 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, + 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, + 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, @@ -862,25 +842,16 @@ const int QmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, - -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, - -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, - 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, - 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, - 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, - 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, - -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, - 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, 55, -1, -1, -1, 59, -1, -1, -1, -1, + -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, + 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, + 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, @@ -891,15 +862,25 @@ const int QmlJSGrammar::action_check [] = { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, - -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, 87, -1, -1, -1, -1, -1, -1, + -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, + 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, + -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, + 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, + 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, @@ -909,45 +890,42 @@ const int QmlJSGrammar::action_check [] = { -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - 13, 94, 3, 19, 33, 23, 13, 3, 23, 3, - 13, 23, 3, 2, 23, 3, 3, 19, 2, 17, - 13, 65, 33, 13, 9, 11, 3, 2, 33, 2, - 13, 13, 13, 3, 34, 3, 33, 13, 3, 13, - 3, 13, 3, 2, 13, 3, 2, 2, 19, 3, - 3, 2, 2, 33, 33, 33, 2, 79, 3, 2, - 2, 13, 3, 2, 13, 79, 33, 33, 3, 13, - 96, 33, 19, 13, 2, 13, 33, 13, 2, 2, - 13, 3, 3, 3, 11, 33, 23, 91, 19, 2, - -1, 2, 2, -1, -1, -1, -1, -1, 13, 13, - -1, 33, -1, -1, 33, -1, 38, -1, 42, 38, - 3, -1, 42, 47, 44, 13, 42, 42, 44, -1, - 3, 35, 47, 42, 42, 42, 42, -1, 47, 47, - 42, 48, 48, 42, 42, 47, 44, 42, 42, 42, - 42, 44, 47, 47, 46, 42, 42, 44, 42, 58, - 46, 42, 42, 44, 42, 42, 42, 47, 42, 47, - 54, 47, 46, 11, 42, 52, 42, 42, 83, 47, - 42, 47, 44, 66, 42, 50, 44, 42, 42, 44, - 13, 42, 42, 66, 45, 45, 42, 98, 44, 11, - 103, 39, 56, 11, 3, 42, 42, 44, 42, 97, - 44, 42, 48, 44, 42, 42, 42, 44, 44, 29, - 48, 42, 42, 33, 44, 42, 47, 39, 42, 42, - 47, 39, -1, 47, 47, 42, 42, 11, 59, 11, - 47, 47, 14, -1, 42, 51, 18, 64, 13, 47, - 64, 64, 26, 27, 42, 53, -1, 64, 42, 47, - 42, 49, 85, 47, 42, 47, -1, 66, 3, 47, - 35, 36, -1, 57, 42, -1, -1, 55, 42, 47, - 4, 49, 64, 47, 42, 49, -1, 11, 4, 47, - 11, 49, -1, 14, -1, 11, -1, 18, 11, -1, - -1, -1, 26, 27, -1, 18, 19, 20, 21, 22, - 26, 27, 33, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + + 3, 2, 15, 25, 25, 3, 25, 3, 2, 11, + 2, 15, 3, 13, 67, 3, 15, 104, 15, 2, + 15, 2, 4, 3, 35, 15, 15, 3, 21, 3, + 93, 15, 2, 2, 19, 13, 15, 96, 25, 25, + 15, 3, 15, 15, 15, 100, 3, 3, 15, 2, + 2, 15, 3, 21, 4, 15, 15, 15, 35, 2, + 21, 2, 2, 2, 98, 3, 2, 2, 2, 35, + 35, 4, 35, 2, 21, 3, 3, 3, 15, 2, + 35, 35, 3, 3, 3, 3, 35, 35, 2, 35, + 21, 35, -1, 35, -1, -1, 13, 2, 13, 44, + 2, 46, 3, 3, 36, -1, -1, -1, 3, -1, + -1, 15, -1, 35, 44, -1, 46, 13, 40, 44, + 44, 46, 46, -1, 41, 15, 41, -1, 44, 15, + 46, 44, 44, 46, 44, 44, 44, 44, 44, 49, + 49, 44, 49, 49, 35, 41, 49, 37, 60, 40, + 58, 44, 44, 46, 46, 44, 44, 44, 3, 44, + 49, 46, 50, 50, 31, 44, 44, 68, 35, 44, + 48, 50, 44, 68, 44, 50, 81, 49, 48, 81, + 44, 85, 44, 44, 44, 49, 48, 44, 49, 49, + 44, 44, 49, 44, 44, 49, 46, 44, 44, 52, + 46, 44, 44, 46, 46, 56, 44, 54, 46, 15, + 3, 44, 44, 99, 47, 47, 44, 44, 46, 46, + 44, 44, 46, 68, 15, 13, 49, 44, 44, 44, + 44, 44, 49, 49, 49, 49, 49, -1, 61, 53, + 28, 29, 55, -1, -1, -1, 37, 38, 44, 66, + 66, 66, 44, 49, 44, 51, -1, 49, 44, 49, + -1, 44, -1, 49, 44, -1, 49, 57, 44, 49, + 46, 51, 44, -1, 66, 68, 59, 49, 44, 51, + 66, 87, 5, 49, 13, 51, 13, 16, 5, 16, + 13, 20, 13, 20, -1, -1, 13, -1, -1, 20, + 21, 22, 23, 24, -1, 28, 29, -1, 35, -1, + -1, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 11, -1, -1, 14, -1, -1, -1, 18, -1, -1, + 13, -1, -1, 16, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -956,5 +934,6 @@ const int QmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1}; + -1, -1, -1}; +QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h index d607e8d..903e2c4 100644 --- a/src/declarative/qml/parser/qmljsgrammar_p.h +++ b/src/declarative/qml/parser/qmljsgrammar_p.h @@ -1,4 +1,3 @@ -// This file was generated by qlalr - DO NOT EDIT! /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). @@ -51,16 +50,21 @@ // We mean it. // +// This file was generated by qlalr - DO NOT EDIT! #ifndef QMLJSGRAMMAR_P_H #define QMLJSGRAMMAR_P_H +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + class QmlJSGrammar { public: enum { EOF_SYMBOL = 0, - REDUCE_HERE = 97, - SHIFT_THERE = 96, + REDUCE_HERE = 99, + SHIFT_THERE = 98, T_AND = 1, T_AND_AND = 2, T_AND_EQ = 3, @@ -87,6 +91,8 @@ public: T_EQ_EQ_EQ = 19, T_FALSE = 83, T_FEED_JS_EXPRESSION = 95, + T_FEED_JS_PROGRAM = 97, + T_FEED_JS_SOURCE_ELEMENT = 96, T_FEED_JS_STATEMENT = 94, T_FEED_UI_OBJECT_MEMBER = 93, T_FEED_UI_PROGRAM = 92, @@ -157,38 +163,33 @@ public: T_XOR = 79, T_XOR_EQ = 80, - ACCEPT_STATE = 630, - RULE_COUNT = 340, - STATE_COUNT = 631, - TERMINAL_COUNT = 98, - NON_TERMINAL_COUNT = 105, + ACCEPT_STATE = 635, + RULE_COUNT = 343, + STATE_COUNT = 636, + TERMINAL_COUNT = 100, + NON_TERMINAL_COUNT = 106, - GOTO_INDEX_OFFSET = 631, - GOTO_INFO_OFFSET = 2618, - GOTO_CHECK_OFFSET = 2618 + GOTO_INDEX_OFFSET = 636, + GOTO_INFO_OFFSET = 2520, + GOTO_CHECK_OFFSET = 2520 }; - static const char *const spell []; - static const int lhs []; - static const int rhs []; - static const int goto_default []; - static const int action_default []; - static const int action_index []; - static const int action_info []; - static const int action_check []; + static const char *const spell []; + static const short lhs []; + static const short rhs []; + static const short goto_default []; + static const short action_default []; + static const short action_index []; + static const short action_info []; + static const short action_check []; static inline int nt_action (int state, int nt) { - const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; - const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; - - const int yyn = goto_index [state] + nt; - - if (yyn < 0 || goto_check [yyn] != nt) + const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; + if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) return goto_default [nt]; - const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; - return goto_info [yyn]; + return action_info [GOTO_INFO_OFFSET + yyn]; } static inline int t_action (int state, int token) @@ -203,5 +204,6 @@ public: }; +QT_END_NAMESPACE #endif // QMLJSGRAMMAR_P_H diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp index 8ca3c30..856d06d 100644 --- a/src/declarative/qml/parser/qmljsparser.cpp +++ b/src/declarative/qml/parser/qmljsparser.cpp @@ -1,8 +1,6 @@ -// This file was generated by qlalr - DO NOT EDIT! - /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -41,18 +39,20 @@ ** ****************************************************************************/ -#include "qmljsparser_p.h" +#include <QtCore/QtDebug> +#include <QtGui/QApplication> + +#include <string.h> #include "qmljsengine_p.h" #include "qmljslexer_p.h" #include "qmljsast_p.h" #include "qmljsnodepool_p.h" -#include <QtCore/QtDebug> -#include <QtCore/QCoreApplication> -#include <QVarLengthArray> -#include <string.h> + +#include "qmljsparser_p.h" +#include <QVarLengthArray> // // This file is automatically generated from qmljs.g. @@ -215,33 +215,43 @@ case 3: { } break; case 4: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 5: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 6: { sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; -case 6: { +case 8: { sym(1).Node = sym(1).UiImportList->finish(); } break; -case 7: { +case 9: { sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport); } break; -case 8: { +case 10: { sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImportList, sym(2).UiImport); } break; -case 11: { +case 13: { sym(1).UiImport->semicolonToken = loc(2); } break; -case 13: { +case 15: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->semicolonToken = loc(3); } break; -case 15: { +case 17: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); @@ -249,14 +259,14 @@ case 15: { sym(1).UiImport->semicolonToken = loc(5); } break; -case 17: { +case 19: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); sym(1).UiImport->importId = sym(3).sval; sym(1).UiImport->semicolonToken = loc(4); } break; -case 18: { +case 20: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { @@ -266,7 +276,7 @@ case 18: { QString text; for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) { text += q->name->asString(); - if (q->next) text += QLatin1Char('.'); + if (q->next) text += QLatin1String("."); } node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId); node->fileNameToken = loc(2); @@ -282,56 +292,56 @@ case 18: { } } break; -case 19: { +case 21: { sym(1).Node = 0; } break; -case 20: { +case 22: { sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); } break; -case 21: { +case 23: { sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); } break; -case 22: { +case 24: { AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; -case 23: { +case 25: { sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember); } break; -case 24: { +case 26: { AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; -case 25: { +case 27: { AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; -case 26: { +case 28: { AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 27: { +case 29: { AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; -case 29: { +case 31: { AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); @@ -340,13 +350,13 @@ case 29: { sym(1).Node = node; } break; -case 30: { +case 32: { AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; -case 31:case 32:case 33:case 34: +case 33:case 34:case 35:case 36: { AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).Statement); @@ -354,35 +364,35 @@ case 31:case 32:case 33:case 34: sym(1).Node = node; } break; -case 35: +case 37: -case 36: { +case 38: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); break; } -case 38: { +case 40: { sym(1).Node = 0; } break; -case 39: { +case 41: { sym(1).Node = sym(1).UiParameterList->finish (); } break; -case 40: { +case 42: { AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval); node->identifierToken = loc(2); sym(1).Node = node; } break; -case 41: { +case 43: { AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; -case 43: { +case 45: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -393,7 +403,7 @@ case 43: { sym(1).Node = node; } break; -case 45: { +case 47: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -403,7 +413,7 @@ case 45: { sym(1).Node = node; } break; -case 47: { +case 49: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); node->typeModifier = sym(2).sval; node->propertyToken = loc(1); @@ -414,7 +424,7 @@ case 47: { sym(1).Node = node; } break; -case 49: { +case 51: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -423,7 +433,7 @@ case 49: { sym(1).Node = node; } break; -case 51: { +case 53: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -434,7 +444,7 @@ case 51: { sym(1).Node = node; } break; -case 53: { +case 55: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, sym(5).Expression); node->propertyToken = loc(1); @@ -445,7 +455,7 @@ case 53: { sym(1).Node = node; } break; -case 55: { +case 57: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, sym(6).Expression); node->isReadonlyMember = true; @@ -458,7 +468,7 @@ case 55: { sym(1).Node = node; } break; -case 57: { +case 59: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, sym(6).Expression); node->isDefaultMember = true; @@ -471,75 +481,75 @@ case 57: { sym(1).Node = node; } break; -case 58: { +case 60: { sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 59: { +case 61: { sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 61: { +case 63: { QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 62: { +case 64: { QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 63: { +case 65: { QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 64: { +case 66: { AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 65: { +case 67: { AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 66: { +case 68: { AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 67: { +case 69: { AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 68: { +case 70: { AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 69: { +case 71: { AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 70: -case 71: { +case 72: +case 73: { AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 72: { +case 74: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -550,7 +560,7 @@ case 72: { sym(1).Node = node; } break; -case 73: { +case 75: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -561,28 +571,28 @@ case 73: { sym(1).Node = node; } break; -case 74: { +case 76: { AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 75: { +case 77: { AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 76: { +case 78: { AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 77: { +case 79: { AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -591,7 +601,7 @@ case 77: { sym(1).Node = node; } break; -case 78: { +case 80: { AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -600,7 +610,7 @@ case 78: { sym(1).Node = node; } break; -case 79: { +case 81: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), @@ -612,7 +622,7 @@ case 79: { sym(1).Node = node; } break; -case 80: { +case 82: { AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); @@ -620,14 +630,14 @@ case 80: { sym(1).Node = node; } break; -case 81: { +case 83: { AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 82: { +case 84: { if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); @@ -647,48 +657,48 @@ case 82: { } } break; -case 83: { +case 85: { sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 84: { +case 86: { sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; -case 85: { +case 87: { AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 86: { +case 88: { AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 87: { +case 89: { AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 88: { +case 90: { AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 89: { +case 91: { AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 90: { +case 92: { AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); @@ -696,40 +706,36 @@ case 90: { sym(1).Node = node; } break; -case 91: { +case 93: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 92: -case 93: { +case 94: +case 95: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 94: { +case 96: { AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 95: { +case 97: { AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 96: { +case 98: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 97: - -case 98: - case 99: case 100: @@ -787,25 +793,29 @@ case 125: case 126: case 127: + +case 128: + +case 129: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); } break; -case 132: { +case 134: { AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 133: { +case 135: { AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 134: { +case 136: { AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -813,316 +823,309 @@ case 134: { sym(1).Node = node; } break; -case 136: { +case 138: { AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 137: { +case 139: { AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 138: { +case 140: { AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 139: { +case 141: { AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 140: { +case 142: { AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 141: { +case 143: { sym(1).Node = 0; } break; -case 142: { +case 144: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 143: { +case 145: { sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); } break; -case 144: { +case 146: { AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 148: { +case 150: { AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 149: { +case 151: { AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 151: { +case 153: { AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 152: { +case 154: { AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 153: { +case 155: { AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 154: { +case 156: { AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 155: { +case 157: { AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 156: { +case 158: { AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 157: { +case 159: { AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 158: { +case 160: { AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 159: { +case 161: { AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 161: { +case 163: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 162: { +case 164: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 163: { +case 165: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 165: { +case 167: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 166: { +case 168: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 168: { +case 170: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 169: { +case 171: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 170: { +case 172: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 172: { +case 174: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 173: { +case 175: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 174: { +case 176: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 175: { +case 177: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 176: { +case 178: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 177: { +case 179: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 179: { +case 181: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 180: { +case 182: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 181: { +case 183: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 182: { +case 184: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 183: { +case 185: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 185: { +case 187: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 186: { +case 188: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 187: { +case 189: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 188: { +case 190: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 190: { +case 192: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 191: { +case 193: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 192: { +case 194: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 193: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - case 195: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); + QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; @@ -1136,7 +1139,7 @@ case 197: { case 199: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); + QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; @@ -1150,7 +1153,7 @@ case 201: { case 203: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); + QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; @@ -1164,7 +1167,7 @@ case 205: { case 207: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); + QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; @@ -1178,7 +1181,7 @@ case 209: { case 211: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); + QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; @@ -1191,6 +1194,13 @@ case 213: { } break; case 215: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 217: { AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1198,7 +1208,7 @@ case 215: { sym(1).Node = node; } break; -case 217: { +case 219: { AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1206,112 +1216,112 @@ case 217: { sym(1).Node = node; } break; -case 219: { +case 221: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 221: { +case 223: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 222: { +case 224: { sym(1).ival = QSOperator::Assign; } break; -case 223: { +case 225: { sym(1).ival = QSOperator::InplaceMul; } break; -case 224: { +case 226: { sym(1).ival = QSOperator::InplaceDiv; } break; -case 225: { +case 227: { sym(1).ival = QSOperator::InplaceMod; } break; -case 226: { +case 228: { sym(1).ival = QSOperator::InplaceAdd; } break; -case 227: { +case 229: { sym(1).ival = QSOperator::InplaceSub; } break; -case 228: { +case 230: { sym(1).ival = QSOperator::InplaceLeftShift; } break; -case 229: { +case 231: { sym(1).ival = QSOperator::InplaceRightShift; } break; -case 230: { +case 232: { sym(1).ival = QSOperator::InplaceURightShift; } break; -case 231: { +case 233: { sym(1).ival = QSOperator::InplaceAnd; } break; -case 232: { +case 234: { sym(1).ival = QSOperator::InplaceXor; } break; -case 233: { +case 235: { sym(1).ival = QSOperator::InplaceOr; } break; -case 235: { +case 237: { AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 236: { +case 238: { sym(1).Node = 0; } break; -case 239: { +case 241: { AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 240: { +case 242: { sym(1).Node = 0; } break; -case 257: { +case 259: { AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 258: { +case 260: { sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); } break; -case 259: { +case 261: { sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); } break; -case 260: { +case 262: { sym(1).Node = 0; } break; -case 261: { +case 263: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 263: { +case 265: { AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1319,76 +1329,76 @@ case 263: { sym(1).Node = node; } break; -case 264: { +case 266: { sym(1).ival = T_CONST; } break; -case 265: { +case 267: { sym(1).ival = T_VAR; } break; -case 266: { +case 268: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 267: { +case 269: { AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 268: { +case 270: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 269: { +case 271: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 270: { +case 272: { AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 271: { +case 273: { AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 272: { +case 274: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 273: { +case 275: { sym(1).Node = 0; } break; -case 275: { +case 277: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 276: { +case 278: { sym(1).Node = 0; } break; -case 278: { +case 280: { AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 280: { +case 282: { AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 281: { +case 283: { AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1397,7 +1407,7 @@ case 281: { sym(1).Node = node; } break; -case 282: { +case 284: { AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1405,7 +1415,7 @@ case 282: { sym(1).Node = node; } break; -case 284: { +case 286: { AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1415,7 +1425,7 @@ case 284: { sym(1).Node = node; } break; -case 285: { +case 287: { AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1423,7 +1433,7 @@ case 285: { sym(1).Node = node; } break; -case 286: { +case 288: { AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1434,7 +1444,7 @@ case 286: { sym(1).Node = node; } break; -case 287: { +case 289: { AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1447,7 +1457,7 @@ case 287: { sym(1).Node = node; } break; -case 288: { +case 290: { AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1457,7 +1467,7 @@ case 288: { sym(1).Node = node; } break; -case 289: { +case 291: { AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1468,14 +1478,14 @@ case 289: { sym(1).Node = node; } break; -case 291: { +case 293: { AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 293: { +case 295: { AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1483,14 +1493,14 @@ case 293: { sym(1).Node = node; } break; -case 295: { +case 297: { AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 297: { +case 299: { AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1498,14 +1508,14 @@ case 297: { sym(1).Node = node; } break; -case 299: { +case 301: { AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 300: { +case 302: { AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1513,7 +1523,7 @@ case 300: { sym(1).Node = node; } break; -case 301: { +case 303: { AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1521,90 +1531,90 @@ case 301: { sym(1).Node = node; } break; -case 302: { +case 304: { AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 303: { +case 305: { AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 304: { +case 306: { sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); } break; -case 305: { +case 307: { sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); } break; -case 306: { +case 308: { sym(1).Node = 0; } break; -case 307: { +case 309: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 308: { +case 310: { AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 309: { +case 311: { AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 310: -case 311: { +case 312: +case 313: { AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 312: { +case 314: { AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 314: { +case 316: { AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 315: { +case 317: { AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 316: { +case 318: { AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 317: { +case 319: { AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 318: { +case 320: { AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1613,20 +1623,20 @@ case 318: { sym(1).Node = node; } break; -case 319: { +case 321: { AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 321: { +case 323: { AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 322: { +case 324: { AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1637,7 +1647,7 @@ case 322: { sym(1).Node = node; } break; -case 323: { +case 325: { AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (sym(2).sval) @@ -1649,56 +1659,60 @@ case 323: { sym(1).Node = node; } break; -case 324: { +case 326: { AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 325: { +case 327: { AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 326: { +case 328: { sym(1).Node = 0; } break; -case 327: { +case 329: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 328: { +case 330: { sym(1).Node = 0; } break; -case 330: { +case 332: { sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 331: { +case 333: { + sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; + +case 334: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); } break; -case 332: { +case 335: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 333: { +case 336: { sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); } break; -case 334: { +case 337: { sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); } break; -case 335: { +case 338: { sym(1).sval = 0; } break; -case 337: { +case 340: { sym(1).Node = 0; } break; @@ -1722,7 +1736,7 @@ case 337: { yylloc.startColumn += yylloc.length; yylloc.length = 0; - //const QString msg = QCoreApplication::translate("QmlParser", "Missing `;'"); + //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; @@ -1747,7 +1761,12 @@ case 337: { token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { - const QString msg = QCoreApplication::translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + QString msg; + int token = token_buffer[0].token; + if (token < 0 || token >= TERMINAL_COUNT) + msg = qApp->translate("QmlParser", "Syntax error"); + else + msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; @@ -1775,7 +1794,7 @@ case 337: { for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QCoreApplication::translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; @@ -1793,12 +1812,13 @@ case 337: { for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || - tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || + tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QCoreApplication::translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; @@ -1811,7 +1831,7 @@ case 337: { } } - const QString msg = QCoreApplication::translate("QmlParser", "Syntax error"); + const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } diff --git a/src/declarative/qml/parser/qmljsparser_p.h b/src/declarative/qml/parser/qmljsparser_p.h index 2cefb5c..42fb422 100644 --- a/src/declarative/qml/parser/qmljsparser_p.h +++ b/src/declarative/qml/parser/qmljsparser_p.h @@ -1,8 +1,6 @@ -// This file was generated by qlalr - DO NOT EDIT! - /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -41,6 +39,7 @@ ** ****************************************************************************/ + // // W A R N I N G // ------------- @@ -133,7 +132,9 @@ public: bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } + bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } + bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast<AST::UiProgram *>(program); } @@ -162,6 +163,9 @@ public: return program->uiObjectMemberCast(); } + AST::Node *rootNode() const + { return program; } + QList<DiagnosticMessage> diagnosticMessages() const { return diagnostic_messages; } @@ -231,9 +235,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 72 +#define J_SCRIPT_REGEXPLITERAL_RULE1 74 -#define J_SCRIPT_REGEXPLITERAL_RULE2 73 +#define J_SCRIPT_REGEXPLITERAL_RULE2 75 QT_QML_END_NAMESPACE diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 1b35442..cd2fbff 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -1,5 +1,4 @@ INCLUDEPATH += $$PWD - SOURCES += \ $$PWD/qmlparser.cpp \ $$PWD/qmlinstruction.cpp \ @@ -32,10 +31,8 @@ SOURCES += \ $$PWD/qmlscriptparser.cpp \ $$PWD/qmlenginedebug.cpp \ $$PWD/qmlrewrite.cpp \ - $$PWD/qmlbasicscript.cpp \ - $$PWD/qmlbindingvme.cpp \ $$PWD/qmlvaluetype.cpp \ - $$PWD/qmlbindingoptimizations.cpp \ + $$PWD/qmlcompiledbindings.cpp \ $$PWD/qmlxmlhttprequest.cpp \ $$PWD/qmlsqldatabase.cpp \ $$PWD/qmetaobjectbuilder.cpp \ @@ -52,8 +49,8 @@ SOURCES += \ $$PWD/qmlvaluetypescriptclass.cpp \ $$PWD/qmltypenamescriptclass.cpp \ $$PWD/qmllistscriptclass.cpp \ - $$PWD/qmlworkerscript.cpp - + $$PWD/qmlworkerscript.cpp \ + $$PWD/qmlnetworkaccessmanagerfactory.cpp HEADERS += \ $$PWD/qmlparser_p.h \ $$PWD/qmlglobal_p.h \ @@ -96,14 +93,12 @@ HEADERS += \ $$PWD/qmldeclarativedata_p.h \ $$PWD/qmlerror.h \ $$PWD/qmlscriptparser_p.h \ - $$PWD/qmlbasicscript_p.h \ - $$PWD/qmlbindingvme_p.h \ $$PWD/qmlenginedebug_p.h \ $$PWD/qmlrewrite_p.h \ $$PWD/qpodvector_p.h \ $$PWD/qbitfield_p.h \ $$PWD/qmlvaluetype_p.h \ - $$PWD/qmlbindingoptimizations_p.h \ + $$PWD/qmlcompiledbindings_p.h \ $$PWD/qmlxmlhttprequest_p.h \ $$PWD/qmlsqldatabase_p.h \ $$PWD/qmetaobjectbuilder_p.h \ @@ -119,10 +114,10 @@ HEADERS += \ $$PWD/qmlvaluetypescriptclass_p.h \ $$PWD/qmltypenamescriptclass_p.h \ $$PWD/qmllistscriptclass_p.h \ - $$PWD/qmlworkerscript_p.h - + $$PWD/qmlworkerscript_p.h \ + $$PWD/qmlscriptclass_p.h \ + $$PWD/qmlguard_p.h \ + $$PWD/qmlnetworkaccessmanagerfactory.h QT += sql - include(parser/parser.pri) include(rewriter/rewriter.pri) - diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp deleted file mode 100644 index 3d566c7..0000000 --- a/src/declarative/qml/qmlbasicscript.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative 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 "qmlbasicscript_p.h" - -#include "qmlengine_p.h" -#include "qmlcontext_p.h" -#include "qmlrefcount_p.h" -#include "qmlglobal_p.h" - -#include <qfxperf_p_p.h> -#include <qmljsast_p.h> -#include <qmljsengine_p.h> - -#include <QColor> -#include <QDebug> -#include <QStack> - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP); - -using namespace QmlJS; - -struct ScriptInstruction { - enum { - LoadIdObject, // fetch - FetchConstant, // constant - FetchContextConstant, // constant - FetchRootConstant, // constant - - Equals, // NA - - Int, // integer - Bool, // boolean - } type; - - union { - struct { - int idx; - } fetch; - struct { - int value; - } integer; - struct { - bool value; - } boolean; - struct { - short idx; - short notify; - int type; - } constant; - }; -}; - -class QmlBasicScriptPrivate -{ -public: - enum Flags { OwnData = 0x00000001 }; - - int size; - int stateSize; - int instructionCount; - int exprLen; - - ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); } - - const char *expr() const - { - return (const char *)(instructions() + instructionCount); - } - - const char *data() const - { - return (const char *)(instructions() + instructionCount) + exprLen + 1; - } - - static unsigned int alignRound(int s) - { - if (s % 4) - s += 4 - (s % 4); - return s; - } -}; - -// anchors.left: (nop convert)(qobject)parent.(anchorline)right - -/* - Property chains: a.b.c.d - if else value selection statements: if(a) b else if(c) d else e - trinary selection: a?b:c - addition: a + b - negation: a - a - equality: == -*/ -static QVariant fetch_value(QObject *o, int idx, int type) -{ - if (!o) - return QVariant(); - - switch(type) { - case QVariant::String: - { - QString val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QVariant::UInt: - { - uint val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QVariant::Int: - { - int val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QMetaType::Float: - { - float val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QVariant::Double: - { - double val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QVariant::Color: - { - QColor val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - case QVariant::Bool: - { - bool val; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - return QVariant(val); - } - break; - default: - { - // If the object is null, we extract the predicted type. While this isn't - // 100% reliable, in many cases it gives us better error messages if we - // assign this null-object to an incompatible property - if (QmlMetaType::isObject(type)) { - // NOTE: This assumes a cast to QObject does not alter the - // object pointer - QObject *val = 0; - void *args[] = { &val, 0 }; - QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args); - if (!val) return QVariant(type, &val); - else return QVariant::fromValue(val); - } else { - QVariant var = o->metaObject()->property(idx).read(o); - if (QmlMetaType::isObject(var.userType())) { - QObject *obj = 0; - obj = *(QObject **)var.data(); - if (!obj) var = QVariant(var.userType(), &obj); - else var = QVariant::fromValue(obj); - } - return var; - } - } - break; - }; -} - -struct QmlBasicScriptCompiler -{ - QmlBasicScriptCompiler() - : script(0), stateSize(0) {} - - QmlBasicScript *script; - int stateSize; - - QmlParser::Object *context; - QmlParser::Object *component; - QHash<QString, QmlParser::Object *> ids; - - bool compile(QmlJS::AST::Node *); - - bool compileExpression(QmlJS::AST::Node *); - - bool tryConstant(QmlJS::AST::Node *); - bool parseConstant(QmlJS::AST::Node *); - bool tryName(QmlJS::AST::Node *); - bool parseName(QmlJS::AST::Node *); - - bool buildName(QStringList &, QmlJS::AST::Node *); - const QMetaObject *fetch(int type, const QMetaObject *, int idx); - - bool tryBinaryExpression(QmlJS::AST::Node *); - bool compileBinaryExpression(QmlJS::AST::Node *); - - QByteArray data; - QList<ScriptInstruction> bytecode; -}; - -/*! - \internal - \class QmlBasicScript - \brief The QmlBasicScript class provides a fast implementation of a limited subset of QmlJS bindings. - - QmlBasicScript instances are used to accelerate binding. Instead of using - the slower, fully fledged QmlJS engine, many simple bindings can be - evaluated using the QmlBasicScript engine. - - To see if the QmlBasicScript engine can handle a binding, call compile() - and check the return value, or isValid() afterwards. - - To accelerate binding, QmlBasicScript can return a precompiled - version of itself that can be saved for future use. Call compileData() to - get an opaque pointer to the compiled state, and compileDataSize() for the - size of this data in bytes. This data can be saved and passed to future - instances of the QmlBasicScript constructor. The initial copy of compile - data is owned by the QmlBindScript instance on which compile() was called. -*/ - -/*! - Create a new QmlBasicScript instance. -*/ -QmlBasicScript::QmlBasicScript() -: flags(0), d(0), rc(0) -{ -} - -/*! - Load the QmlBasicScript instance with saved \a data. - - \a data \b must be data previously acquired from calling compileData() on a - previously created QmlBasicScript instance. Any other data will almost - certainly cause the QmlBasicScript engine to crash. - - \a data must continue to be valid throughout the QmlBasicScript instance - life. It does not assume ownership of the memory. - - If \a owner is set, it is referenced on creation and dereferenced on - destruction of this instance. -*/ - -void QmlBasicScript::load(const char *data, QmlRefCount *owner) -{ - clear(); - d = (QmlBasicScriptPrivate *)data; - rc = owner; - if (rc) rc->addref(); -} - -/*! - Return the text of the script expression. - */ -QByteArray QmlBasicScript::expression() const -{ - if (!d) - return QByteArray(); - else - return QByteArray(d->expr()); -} - -/*! - Destroy the script instance. -*/ -QmlBasicScript::~QmlBasicScript() -{ - clear(); -} - -/*! - Clear this script. The object will then be in its initial state, as though - it were freshly constructed with default constructor. -*/ -void QmlBasicScript::clear() -{ - if (flags & QmlBasicScriptPrivate::OwnData) - free(d); - if (rc) rc->release(); - d = 0; - rc = 0; - flags = 0; -} - -/*! - Dump the script instructions to stderr for debugging. - */ -void QmlBasicScript::dump() -{ - if (!d) - return; - - qWarning() << d->instructionCount << "instructions:"; - for (int ii = 0; ii < d->instructionCount; ++ii) { - const ScriptInstruction &instr = d->instructions()[ii]; - - switch(instr.type) { - case ScriptInstruction::LoadIdObject: - qWarning().nospace() << "LOAD_ID_OBJECT"; - break; - case ScriptInstruction::FetchConstant: - qWarning().nospace() << "FETCH_CONSTANT"; - break; - case ScriptInstruction::FetchContextConstant: - qWarning().nospace() << "FETCH_CONTEXT_CONSTANT"; - break; - case ScriptInstruction::FetchRootConstant: - qWarning().nospace() << "FETCH_ROOT_CONSTANT"; - break; - case ScriptInstruction::Equals: - qWarning().nospace() << "EQUALS"; - break; - case ScriptInstruction::Int: - qWarning().nospace() << "INT\t\t" << instr.integer.value; - break; - case ScriptInstruction::Bool: - qWarning().nospace() << "BOOL\t\t" << instr.boolean.value; - break; - default: - qWarning().nospace() << "UNKNOWN"; - break; - } - } -} - -/*! - Return true if this is a valid script binding, otherwise returns false. - */ -bool QmlBasicScript::isValid() const -{ - return d != 0; -} - -bool QmlBasicScript::compile(const Expression &expression) -{ - if (!expression.expression.asAST()) return false; - - QByteArray expr = expression.expression.asScript().toUtf8(); - const char *src = expr.constData(); - - QmlBasicScriptCompiler bsc; - bsc.script = this; - bsc.context = expression.context; - bsc.component = expression.component; - bsc.ids = expression.ids; - - if (d) { - if (flags & QmlBasicScriptPrivate::OwnData) - free(d); - d = 0; - flags = 0; - } - - if (bsc.compile(expression.expression.asAST())) { - int len = ::strlen(src); - flags = QmlBasicScriptPrivate::OwnData; - int size = sizeof(QmlBasicScriptPrivate) + - bsc.bytecode.count() * sizeof(ScriptInstruction) + - QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1); - d = (QmlBasicScriptPrivate *) malloc(size); - d->size = size; - d->stateSize = bsc.stateSize; - d->instructionCount = bsc.bytecode.count(); - d->exprLen = len; - ::memcpy((char *)d->expr(), src, len + 1); - for (int ii = 0; ii < d->instructionCount; ++ii) - d->instructions()[ii] = bsc.bytecode.at(ii); - ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count()); - } - - if (d && qmlBasicScriptDump()) - dump(); - return d != 0; -} - -bool QmlBasicScriptCompiler::compile(QmlJS::AST::Node *node) -{ - return compileExpression(node); -} - -bool QmlBasicScriptCompiler::tryConstant(QmlJS::AST::Node *node) -{ - if (node->kind == AST::Node::Kind_TrueLiteral || - node->kind == AST::Node::Kind_FalseLiteral) - return true; - - if (node->kind == AST::Node::Kind_NumericLiteral) { - AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node); - - return double(int(lit->value)) == lit->value; - } - - return false; -} - -bool QmlBasicScriptCompiler::parseConstant(QmlJS::AST::Node *node) -{ - ScriptInstruction instr; - - if (node->kind == AST::Node::Kind_NumericLiteral) { - AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node); - instr.type = ScriptInstruction::Int; - instr.integer.value = int(lit->value); - } else { - instr.type = ScriptInstruction::Bool; - instr.boolean.value = node->kind == AST::Node::Kind_TrueLiteral; - } - - bytecode.append(instr); - - return true; -} - -bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node) -{ - return node->kind == AST::Node::Kind_IdentifierExpression || - node->kind == AST::Node::Kind_FieldMemberExpression; -} - -bool QmlBasicScriptCompiler::buildName(QStringList &name, - QmlJS::AST::Node *node) -{ - if (node->kind == AST::Node::Kind_IdentifierExpression) { - name << static_cast<AST::IdentifierExpression*>(node)->name->asString(); - } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { - AST::FieldMemberExpression *expr = - static_cast<AST::FieldMemberExpression *>(node); - - if (!buildName(name, expr->base)) - return false; - - name << expr->name->asString(); - } else { - return false; - } - - return true; -} - -const QMetaObject * -QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx) -{ - ScriptInstruction instr; - *((int*)&instr.type) = type; - instr.constant.idx = idx; - QMetaProperty prop = mo->property(idx); - if (prop.isConstant()) - instr.constant.notify = 0; - else - instr.constant.notify = prop.notifySignalIndex(); - instr.constant.type = prop.userType(); - bytecode << instr; - return QmlMetaType::metaObjectForType(prop.userType()); -} - -bool QmlBasicScriptCompiler::parseName(AST::Node *node) -{ - QStringList nameParts; - if (!buildName(nameParts, node)) - return false; - - QmlParser::Object *absType = 0; - const QMetaObject *metaType = 0; - - for (int ii = 0; ii < nameParts.count(); ++ii) { - const QString &name = nameParts.at(ii); - - // We don't handle signal properties - if (name.length() > 2 && name.startsWith(QLatin1String("on")) && - name.at(2).isUpper()) - return false; - - if (ii == 0) { - - if (0) { - // ### - Must test for an attached type name - } else if (ids.contains(name)) { - ScriptInstruction instr; - instr.type = ScriptInstruction::LoadIdObject; - instr.fetch.idx = ids.value(name)->idIndex; - bytecode << instr; - absType = ids.value(name); - } else if(name.at(0).isLower()) { - - QByteArray utf8Name = name.toUtf8(); - const char *cname = utf8Name.constData(); - - int d0Idx = context->metaObject()->indexOfProperty(cname); - int d1Idx = -1; - if (d0Idx == -1) - d1Idx = component->metaObject()->indexOfProperty(cname); - - if (d0Idx != -1) { - metaType = fetch(ScriptInstruction::FetchContextConstant, - context->metaObject(), d0Idx); - } else if(d1Idx != -1) { - metaType = fetch(ScriptInstruction::FetchRootConstant, - component->metaObject(), d1Idx); - } else { - return false; - } - - } else { - return false; - } - } else { - - if (!name.at(0).isLower()) - return false; - - const QMetaObject *mo = 0; - if (absType) - mo = absType->metaObject(); - else if(metaType) - mo = metaType; - else - return false; - - QByteArray utf8Name = name.toUtf8(); - const char *cname = utf8Name.constData(); - int idx = mo->indexOfProperty(cname); - if (idx == -1) - return false; - - if (absType || mo->property(idx).isFinal()) { - absType = 0; metaType = 0; - metaType = fetch(ScriptInstruction::FetchConstant, mo, idx); - } else { - return false; - } - - } - } - - return true; -} - -bool QmlBasicScriptCompiler::compileExpression(QmlJS::AST::Node *node) -{ - if (tryBinaryExpression(node)) - return compileBinaryExpression(node); - else if (tryConstant(node)) - return parseConstant(node); - else if (tryName(node)) - return parseName(node); - else - return false; -} - -bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node) -{ - if (node->kind == AST::Node::Kind_BinaryExpression) { - AST::BinaryExpression *expr = - static_cast<AST::BinaryExpression *>(node); - - if (expr->op == QSOperator::Equal) - return true; - } - return false; -} - -bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node) -{ - if (node->kind == AST::Node::Kind_BinaryExpression) { - AST::BinaryExpression *expr = - static_cast<AST::BinaryExpression *>(node); - - if (!compileExpression(expr->left)) return false; - if (!compileExpression(expr->right)) return false; - - ScriptInstruction instr; - switch (expr->op) { - case QSOperator::Equal: - instr.type = ScriptInstruction::Equals; - break; - default: - return false; - } - - bytecode.append(instr); - return true; - } - return false; -} - -/*! - Run the script in \a context and return the result. - */ -QVariant QmlBasicScript::run(QmlContext *context, QObject *me) -{ - if (!isValid()) - return QVariant(); - - QmlContextPrivate *contextPrivate = context->d_func(); - QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(context->engine()); - - QStack<QVariant> stack; - - for (int idx = 0; idx < d->instructionCount; ++idx) { - const ScriptInstruction &instr = d->instructions()[idx]; - - switch(instr.type) { - case ScriptInstruction::LoadIdObject: - { - stack.push(QVariant::fromValue(contextPrivate->idValues[instr.fetch.idx].data())); - enginePrivate->capturedProperties << - QmlEnginePrivate::CapturedProperty(context, -1, contextPrivate->notifyIndex + instr.fetch.idx); - } - break; - - case ScriptInstruction::FetchContextConstant: - { - stack.push(fetch_value(me, instr.constant.idx, instr.constant.type)); - if (me && instr.constant.notify != 0) - enginePrivate->capturedProperties << - QmlEnginePrivate::CapturedProperty(me, instr.constant.idx, instr.constant.notify); - } - break; - - case ScriptInstruction::FetchRootConstant: - { - QObject *obj = contextPrivate->defaultObjects.at(0); - - stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (obj && instr.constant.notify != 0) - enginePrivate->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); - } - break; - - case ScriptInstruction::FetchConstant: - { - QVariant o = stack.pop(); - QObject *obj = *(QObject **)o.constData(); - - stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (obj && instr.constant.notify != 0) - enginePrivate->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); - } - break; - - case ScriptInstruction::Int: - stack.push(QVariant(instr.integer.value)); - break; - - case ScriptInstruction::Bool: - stack.push(QVariant(instr.boolean.value)); - break; - - case ScriptInstruction::Equals: - { - QVariant rhs = stack.pop(); - QVariant lhs = stack.pop(); - - stack.push(rhs == lhs); - } - break; - default: - break; - } - } - - if (stack.isEmpty()) - return QVariant(); - else - return stack.top(); -} - -bool QmlBasicScript::isSingleIdFetch() const -{ - if (!isValid()) - return false; - - return d->instructionCount == 1 && - d->instructions()[0].type == ScriptInstruction::LoadIdObject; -} - -int QmlBasicScript::singleIdFetchIndex() const -{ - if (!isSingleIdFetch()) - return -1; - - return d->instructions()[0].fetch.idx; -} - -/*! - Return a pointer to the script's compile data, or null if there is no data. - */ -const char *QmlBasicScript::compileData() const -{ - return (const char *)d; -} - -/*! - Return the size of the script's compile data, or zero if there is no data. - The size will always be a multiple of 4. - */ -unsigned int QmlBasicScript::compileDataSize() const -{ - if (d) - return d->size; - else - return 0; -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 4ec7191..3e29a3c 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); QmlBindingData::QmlBindingData() -: updating(false), enabled(false), nextError(0), prevError(0) +: updating(false), enabled(false) { } @@ -78,37 +78,6 @@ void QmlBindingData::refresh() } } -void QmlBindingData::removeError() -{ - if (!prevError) return; - - if (nextError) nextError->prevError = prevError; - *prevError = nextError; - nextError = 0; - prevError = 0; -} - -bool QmlBindingData::addError() -{ - if (prevError) return false; - - QmlContext *c = context(); - if (!c) return false; - QmlEngine *e = c->engine(); - if (!e) return false; - - QmlEnginePrivate *p = QmlEnginePrivate::get(e); - - if (p->inProgressCreations == 0) return false; // Not in construction - - prevError = &p->erroredBindings; - nextError = p->erroredBindings; - p->erroredBindings = this; - if (nextError) nextError->prevError = &nextError; - - return true; -} - QmlBindingPrivate::QmlBindingPrivate() : QmlExpressionPrivate(new QmlBindingData) { @@ -178,7 +147,11 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags) bool isUndefined = false; QVariant value = this->value(&isUndefined); - if (isUndefined && !data->error.isValid()) { + if (isUndefined && !data->error.isValid() && data->property.isResettable()) { + + data->property.reset(); + + } else if (isUndefined && !data->error.isValid()) { QUrl url = QUrl(data->url); int line = data->line; @@ -190,7 +163,7 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags) data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType()))); } else if (!isUndefined && data->property.object() && - !data->property.write(value, flags)) { + !data->property.write(value, flags)) { QUrl url = QUrl(data->url); int line = data->line; @@ -210,7 +183,9 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags) } if (data->error.isValid()) { - if (!data->addError()) + QmlEnginePrivate *p = (data->context() && data->context()->engine())? + QmlEnginePrivate::get(data->context()->engine()):0; + if (!data->addError(p)) qWarning().nospace() << qPrintable(this->error().toString()); } else { data->removeError(); diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index 945b659..c6c1935 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -72,10 +72,6 @@ public: QmlMetaProperty property; virtual void refresh(); - void removeError(); - bool addError(); - QmlBindingData *nextError; - QmlBindingData **prevError; }; class QmlBindingPrivate : public QmlExpressionPrivate diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp deleted file mode 100644 index 868440e..0000000 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative 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 "qmlbindingoptimizations_p.h" - -#include "qmlcontext_p.h" -#include <QtDeclarative/qmlinfo.h> -#include "qmlbindingvme_p.h" - -QT_BEGIN_NAMESPACE - -int QmlOptimizedBindings::methodCount = -1; - -QmlOptimizedBindings::QmlOptimizedBindings(const char *program, QmlContext *context) -: m_program(program) -{ - if (methodCount == -1) - methodCount = QmlOptimizedBindings::staticMetaObject.methodCount(); - - m_config.target = this; - m_config.targetSlot = metaObject()->methodCount(); - - quint32 bindings = 0; - QmlBindingVME::init(m_program, &m_config, &m_signalTable, &bindings); - - m_bindings = new Binding[bindings]; - - QmlAbstractExpression::setContext(context); -} - -QmlOptimizedBindings::~QmlOptimizedBindings() -{ - delete [] m_bindings; -} - -QmlAbstractBinding *QmlOptimizedBindings::configBinding(int index, QObject *target, - QObject *scope, int property) -{ - Binding *rv = m_bindings + index; - - rv->index = index; - rv->property = property; - rv->target = target; - rv->scope = scope; - rv->parent = this; - - addref(); // This is decremented in Binding::destroy() - - return rv; -} - -void QmlOptimizedBindings::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) -{ - if (e) { - addToObject(target); - update(flags); - } else { - removeFromObject(); - } - - QmlAbstractBinding::setEnabled(e, flags); - - if (enabled != e) { - enabled = e; - - if (e) update(flags); - } -} - -int QmlOptimizedBindings::Binding::propertyIndex() -{ - return property & 0xFFFF; -} - -void QmlOptimizedBindings::Binding::update(QmlMetaProperty::WriteFlags) -{ - parent->run(this); -} - -void QmlOptimizedBindings::Binding::destroy() -{ - enabled = false; - removeFromObject(); - parent->release(); -} - -int QmlOptimizedBindings::qt_metacall(QMetaObject::Call c, int id, void **) -{ - if (c == QMetaObject::InvokeMetaMethod && id >= methodCount) { - id -= methodCount; - - quint32 *reeval = m_signalTable + m_signalTable[id]; - quint32 count = *reeval; - ++reeval; - for (quint32 ii = 0; ii < count; ++ii) { - run(m_bindings + reeval[ii]); - } - } - return -1; -} - -void QmlOptimizedBindings::run(Binding *binding) -{ - if (!binding->enabled) - return; - if (binding->updating) - qWarning("ERROR: Circular binding"); - - QmlContext *context = QmlAbstractExpression::context(); - if (!context) { - qWarning("QmlOptimizedBindings: Attempted to evaluate an expression in an invalid context"); - return; - } - QmlContextPrivate *cp = QmlContextPrivate::get(context); - - if (binding->property & 0xFFFF0000) { - QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine); - - QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - vt->read(binding->target, binding->property & 0xFFFF); - - QObject *target = vt; - QmlBindingVME::run(m_program, binding->index, &m_config, cp, - &binding->scope, &target); - - vt->write(binding->target, binding->property & 0xFFFF, - QmlMetaProperty::DontRemoveBinding); - } else { - QmlBindingVME::run(m_program, binding->index, &m_config, cp, - &binding->scope, &binding->target); - } -} - -/* - The QmlBinding_Id optimization handles expressions of the type: - - property: id - - where id is a local context id, and property is an object property. - Coercian between id and property must be checked outside the QmlBinding_Id - - it assumes that they coerce successfully. - - The QmlBinding_Id class avoids any signal slot connections, through the - special "bindings" linked list maintained in the - QmlContextPrivate::ContextGuard instance for each id object. -*/ -QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx, - QmlContext *context, int id) -: m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id) -{ - QmlAbstractExpression::setContext(context); -} - -QmlBinding_Id::~QmlBinding_Id() -{ - removeFromContext(); -} - -void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) -{ - if (e) { - addToObject(m_object); - update(flags); - } else { - removeFromObject(); - } - - QmlAbstractBinding::setEnabled(e, flags); -} - -int QmlBinding_Id::propertyIndex() -{ - return m_propertyIdx; -} - -void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags) -{ - QmlContextPrivate *ctxtPriv = - static_cast<QmlContextPrivate *>(QObjectPrivate::get(context())); - - if (ctxtPriv) { - - if (!m_prev) { - m_next = ctxtPriv->idValues[m_id].bindings; - if (m_next) m_next->m_prev = &m_next; - - m_prev = &ctxtPriv->idValues[m_id].bindings; - ctxtPriv->idValues[m_id].bindings = this; - } - - QObject *o = ctxtPriv->idValues[m_id].data(); - int status = -1; - void *a[] = { &o, 0, &status, &flags }; - QMetaObject::metacall(m_object, QMetaObject::WriteProperty, - m_propertyIdx, a); - } -} - -void QmlBinding_Id::removeFromContext() -{ - if (m_prev) { - *m_prev = m_next; - if (m_next) m_next->m_prev = m_prev; - m_next = 0; - m_prev = 0; - } -} - -void QmlBinding_Id::reset() -{ - removeFromContext(); - - QObject *o = 0; - int status = -1; - QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding; - void *a[] = { &o, 0, &status, &flags }; - QMetaObject::metacall(m_object, QMetaObject::WriteProperty, - m_propertyIdx, a); -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h deleted file mode 100644 index feb753e..0000000 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative 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 QMLBINDINGOPTIMIZATIONS_P_H -#define QMLBINDINGOPTIMIZATIONS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qmlexpression_p.h" -#include "qmlbinding.h" -#include "qmlbasicscript_p.h" -#include "qmlbindingvme_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QmlOptimizedBindings : public QObject, public QmlAbstractExpression, public QmlRefCount -{ -public: - QmlOptimizedBindings(const char *program, QmlContext *context); - virtual ~QmlOptimizedBindings(); - QmlAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); - -protected: - int qt_metacall(QMetaObject::Call, int, void **); - -private: - struct Binding : public QmlAbstractBinding { - Binding() : enabled(false), updating(0), property(0), - scope(0), target(0), parent(0) {} - - // Inherited from QmlAbstractBinding - virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); - virtual int propertyIndex(); - virtual void update(QmlMetaProperty::WriteFlags flags); - virtual void destroy(); - - int index:30; - bool enabled:1; - bool updating:1; - int property; - QObject *scope; - QObject *target; - - QmlOptimizedBindings *parent; - }; - void run(Binding *); - - QmlBindingVME::Config m_config; - const char *m_program; - Binding *m_bindings; - quint32 *m_signalTable; - - static int methodCount; -}; - -class QmlBinding_Id : public QmlAbstractExpression, - public QmlAbstractBinding -{ -public: - QmlBinding_Id(QObject *object, int propertyIdx, - QmlContext *context, int id); - virtual ~QmlBinding_Id(); - - // Inherited from QmlAbstractBinding - virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); - virtual int propertyIndex(); - virtual void update(QmlMetaProperty::WriteFlags flags); - - void reset(); - -private: - void removeFromContext(); - - QmlBinding_Id **m_prev; - QmlBinding_Id *m_next; - - QObject *m_object; - int m_propertyIdx; - int m_id; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QMLBINDINGOPTIMIZATIONS_P_H - diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlcompiledbindings.cpp index 16b0a21..d09f7eb 100644 --- a/src/declarative/qml/qmlbindingvme.cpp +++ b/src/declarative/qml/qmlcompiledbindings.cpp @@ -39,11 +39,15 @@ ** ****************************************************************************/ -#include "qmlbindingvme_p.h" +#include "qmlcompiledbindings_p.h" + +#include <QtDeclarative/qmlinfo.h> #include <private/qmlcontext_p.h> #include <private/qmljsast_p.h> #include <private/qmljsengine_p.h> +#include <private/qmlexpression_p.h> #include <QtCore/qdebug.h> +#include <QtCore/qnumeric.h> #include <private/qmlgraphicsanchors_p_p.h> QT_BEGIN_NAMESPACE @@ -53,32 +57,293 @@ using namespace QmlJS; namespace { // Supported types: int, qreal, QString (needs constr/destr), QObject*, bool struct Register { - void setQObject(QObject *o) { *((QObject **)data) = o; } - QObject *getQObject() { return *((QObject **)data); } + void setUndefined() { type = 0; } + void setUnknownButDefined() { type = -1; } + void setNaN() { setqreal(qSNaN()); } + bool isUndefined() const { return type == 0; } + + void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; } + QObject *getQObject() const { return *((QObject **)data); } - void setqreal(qreal v) { *((qreal *)data) = v; } - qreal getqreal() { return *((qreal *)data); } + void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; } + qreal getqreal() const { return *((qreal *)data); } - void setint(int v) { *((int *)data) = v; } - int getint() { return *((int *)data); } + void setint(int v) { *((int *)data) = v; type = QMetaType::Int; } + int getint() const { return *((int *)data); } - void setbool(bool v) { *((bool *)data) = v; } - bool getbool() { return *((bool *)data); } + void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; } + bool getbool() const { return *((bool *)data); } QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } QString *getstringptr() { return (QString *)typeDataPtr(); } QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } + const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } + const QString *getstringptr() const { return (QString *)typeDataPtr(); } + const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } void *typeDataPtr() { return (void *)&data; } void *typeMemory() { return (void *)data; } + const void *typeDataPtr() const { return (void *)&data; } + const void *typeMemory() const { return (void *)data; } - int gettype() { return type; } + int gettype() const { return type; } void settype(int t) { type = t; } int type; // Optional type void *data[2]; // Object stored here }; +} + +class QmlCompiledBindingsPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlCompiledBindings) + +public: + QmlCompiledBindingsPrivate(); + virtual ~QmlCompiledBindingsPrivate(); + + struct Binding : public QmlAbstractBinding, public QmlDelayedError { + Binding() : enabled(false), updating(0), property(0), + scope(0), target(0), parent(0) {} + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); + virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); + virtual void destroy(); + + int index:30; + bool enabled:1; + bool updating:1; + int property; + QObject *scope; + QObject *target; + + QmlCompiledBindingsPrivate *parent; + }; + + struct Subscription { + struct Signal { + QmlGuard<QObject> source; + int notifyIndex; + }; + + enum { InvalidType, SignalType, IdType } type; + inline Subscription(); + inline ~Subscription(); + bool isSignal() const { return type == SignalType; } + bool isId() const { return type == IdType; } + inline Signal *signal(); + inline QmlContextPrivate::IdNotifier *id(); + union { + char signalData[sizeof(Signal)]; + char idData[sizeof(QmlContextPrivate::IdNotifier)]; + }; + }; + Subscription *subscriptions; + QScriptDeclarativeClass::PersistentIdentifier *identifiers; + + void run(Binding *); + + const char *programData; + Binding *m_bindings; + quint32 *m_signalTable; + + static int methodCount; + + void init(); + void run(int instr, QmlContextPrivate *context, + QmlDelayedError *error, QObject *scope, QObject *output); + + + inline void unsubscribe(int subIndex); + inline void subscribeId(QmlContextPrivate *p, int idIndex, int subIndex); + inline void subscribe(QObject *o, int notifyIndex, int subIndex); + + QmlPropertyCache::Data *findproperty(QObject *obj, + const QScriptDeclarativeClass::Identifier &name, + QmlEnginePrivate *enginePriv, + QmlPropertyCache::Data &local); + bool findproperty(QObject *obj, + Register *output, + QmlEnginePrivate *enginePriv, + int subIdx, + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal); + void findgeneric(Register *output, // value output + int subIdx, // Subscription index in config + QmlContextPrivate *context, // Context to search in + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal); +}; + +QmlCompiledBindingsPrivate::QmlCompiledBindingsPrivate() +: subscriptions(0), identifiers(0) +{ +} + +QmlCompiledBindingsPrivate::~QmlCompiledBindingsPrivate() +{ + delete [] subscriptions; subscriptions = 0; + delete [] identifiers; identifiers = 0; +} + +QmlCompiledBindingsPrivate::Subscription::Subscription() +: type(InvalidType) +{ +} + +QmlCompiledBindingsPrivate::Subscription::~Subscription() +{ + if (type == SignalType) ((Signal *)signalData)->~Signal(); + else if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier(); +} + + +int QmlCompiledBindingsPrivate::methodCount = -1; +QmlCompiledBindings::QmlCompiledBindings(const char *program, QmlContext *context) +: QObject(*(new QmlCompiledBindingsPrivate)) +{ + Q_D(QmlCompiledBindings); + + if (d->methodCount == -1) + d->methodCount = QmlCompiledBindings::staticMetaObject.methodCount(); + + d->programData = program; + + d->init(); + + QmlAbstractExpression::setContext(context); +} + +QmlCompiledBindings::~QmlCompiledBindings() +{ + Q_D(QmlCompiledBindings); + + delete [] d->m_bindings; +} + +QmlAbstractBinding *QmlCompiledBindings::configBinding(int index, QObject *target, + QObject *scope, int property) +{ + Q_D(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Binding *rv = d->m_bindings + index; + + rv->index = index; + rv->property = property; + rv->target = target; + rv->scope = scope; + rv->parent = d; + + addref(); // This is decremented in Binding::destroy() + + return rv; +} + +void QmlCompiledBindingsPrivate::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) +{ + if (e) { + addToObject(target); + update(flags); + } else { + removeFromObject(); + } + + QmlAbstractBinding::setEnabled(e, flags); + + if (enabled != e) { + enabled = e; + + if (e) update(flags); + } +} + +int QmlCompiledBindingsPrivate::Binding::propertyIndex() +{ + return property & 0xFFFF; +} + +void QmlCompiledBindingsPrivate::Binding::update(QmlMetaProperty::WriteFlags) +{ + parent->run(this); +} + +void QmlCompiledBindingsPrivate::Binding::destroy() +{ + enabled = false; + removeFromObject(); + parent->q_func()->release(); +} + +int QmlCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **) +{ + Q_D(QmlCompiledBindings); + + if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) { + id -= d->methodCount; + + quint32 *reeval = d->m_signalTable + d->m_signalTable[id]; + quint32 count = *reeval; + ++reeval; + for (quint32 ii = 0; ii < count; ++ii) { + d->run(d->m_bindings + reeval[ii]); + } + } + return -1; +} + +void QmlCompiledBindingsPrivate::run(Binding *binding) +{ + Q_Q(QmlCompiledBindings); + + if (!binding->enabled) + return; + if (binding->updating) + qWarning("ERROR: Circular binding"); + + QmlContext *context = q->QmlAbstractExpression::context(); + if (!context) { + qWarning("QmlCompiledBindings: Attempted to evaluate an expression in an invalid context"); + return; + } + QmlContextPrivate *cp = QmlContextPrivate::get(context); + + if (binding->property & 0xFFFF0000) { + QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine); + + QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + vt->read(binding->target, binding->property & 0xFFFF); + + QObject *target = vt; + run(binding->index, cp, binding, binding->scope, target); + + vt->write(binding->target, binding->property & 0xFFFF, + QmlMetaProperty::DontRemoveBinding); + } else { + run(binding->index, cp, binding, binding->scope, binding->target); + } +} + +QmlCompiledBindingsPrivate::Subscription::Signal *QmlCompiledBindingsPrivate::Subscription::signal() +{ + if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier(); + if (type != SignalType) new (signalData) Signal; + type = SignalType; + return (Signal *)signalData; +} + +QmlContextPrivate::IdNotifier *QmlCompiledBindingsPrivate::Subscription::id() +{ + if (type == SignalType) ((Signal *)signalData)->~Signal(); + if (type != IdType) new (idData) QmlContextPrivate::IdNotifier; + type = IdType; + return (QmlContextPrivate::IdNotifier *)idData; +} + +namespace { // This structure is exactly 8-bytes in size struct Instr { enum { @@ -171,21 +436,21 @@ struct Instr { quint8 type; qint8 output; qint8 reg; - quint8 packing[1]; + quint8 exceptionId; quint32 index; } attached; struct { quint8 type; qint8 output; qint8 reg; - quint8 packing[1]; + quint8 exceptionId; quint32 index; } store; struct { quint8 type; qint8 output; qint8 objectReg; - quint8 packing[1]; + quint8 exceptionId; quint32 index; } fetch; struct { @@ -246,7 +511,7 @@ struct Instr { quint8 type; qint8 reg; qint8 src; - quint8 packing[1]; + quint8 exceptionId; quint16 name; quint16 subscribeIndex; } find; @@ -268,6 +533,7 @@ struct Program { quint32 bindings; quint32 dataLength; quint32 signalTableOffset; + quint32 exceptionDataOffset; quint16 subscriptions; quint16 identifiers; quint16 instructionCount; @@ -337,8 +603,8 @@ struct QmlBindingCompilerPrivate bool tryMethod(QmlJS::AST::Node *); bool parseMethod(QmlJS::AST::Node *, Result &); - bool buildName(QStringList &, QmlJS::AST::Node *); - bool fetch(Result &type, const QMetaObject *, int reg, int idx, const QStringList &); + bool buildName(QStringList &, QmlJS::AST::Node *, QList<QmlJS::AST::ExpressionNode *> *nodes = 0); + bool fetch(Result &type, const QMetaObject *, int reg, int idx, const QStringList &, QmlJS::AST::ExpressionNode *); quint32 registers; QHash<int, QPair<int, int> > registerCleanups; @@ -355,6 +621,9 @@ struct QmlBindingCompilerPrivate int subscriptionIndex(const QStringList &); bool subscriptionNeutral(const QSet<QString> &base, const QSet<QString> &lhs, const QSet<QString> &rhs); + quint8 exceptionId(QmlJS::AST::ExpressionNode *); + QVector<quint64> exceptions; + QSet<int> usedSubscriptionIds; QSet<QString> subscriptionSet; QHash<QString, int> subscriptionIds; @@ -368,6 +637,7 @@ struct QmlBindingCompilerPrivate QVector<Instr> bytecode; QByteArray data; QHash<QString, int> subscriptionIds; + QVector<quint64> exceptions; QHash<QString, QPair<int, int> > registeredStrings; @@ -375,35 +645,173 @@ struct QmlBindingCompilerPrivate } committed; QByteArray buildSignalTable() const; + QByteArray buildExceptionData() const; }; -inline void subscribe(QObject *o, int notifyIndex, - int subIndex, QmlBindingVME::Config *config) +void QmlCompiledBindingsPrivate::unsubscribe(int subIndex) +{ + Q_Q(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); + if (sub->isSignal()) { + QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); + if (s->source) +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + QMetaObject::disconnectOne(s->source, s->notifyIndex, + q, methodCount + subIndex); +#else + // QTBUG-6781 + QMetaObject::disconnect(s->source, s->notifyIndex, + q, methodCount + subIndex); +#endif + } else if (sub->isId()) { + sub->id()->clear(); + } +} + +void QmlCompiledBindingsPrivate::subscribeId(QmlContextPrivate *p, int idIndex, int subIndex) { - QmlBindingVME::Config::Subscription *s = config->subscriptions + subIndex; + Q_Q(QmlCompiledBindings); + + unsubscribe(subIndex); + + if (p->idValues[idIndex]) { + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); + QmlContextPrivate::IdNotifier *i = sub->id(); + + i->next = p->idValues[idIndex].bindings; + i->prev = &p->idValues[idIndex].bindings; + p->idValues[idIndex].bindings = i; + if (i->next) i->next->prev = &i->next; + + i->target = q; + i->methodIndex = methodCount + subIndex; + } +} + +void QmlCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex) +{ + Q_Q(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); + + if (sub->isId()) + unsubscribe(subIndex); + + QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); if (o != s->source || notifyIndex != s->notifyIndex) { if (s->source) +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + q, methodCount + subIndex); +#else + // QTBUG-6781 + QMetaObject::disconnect(s->source, s->notifyIndex, + q, methodCount + subIndex); +#endif s->source = o; s->notifyIndex = notifyIndex; if (s->source && s->notifyIndex != -1) - QMetaObject::connect(s->source, s->notifyIndex, config->target, - config->targetSlot + subIndex, Qt::DirectConnection); + QMetaObject::connect(s->source, s->notifyIndex, q, + methodCount + subIndex, Qt::DirectConnection); } } +// Conversion functions - these MUST match the QtScript expression path +inline static qreal toReal(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return reg->getqreal(); + } else if (type == qMetaTypeId<QVariant>()) { + return reg->getvariantptr()->toReal(); + } else { + if (ok) *ok = false; + return 0; + } +} + +inline static QString toString(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return QString::number(reg->getqreal()); + } else if (type == QMetaType::Int) { + return QString::number(reg->getint()); + } else if (type == qMetaTypeId<QVariant>()) { + return reg->getvariantptr()->toString(); + } else if (type == QMetaType::QString) { + return *reg->getstringptr(); + } else { + if (ok) *ok = false; + return QString(); + } +} + +inline static bool toBool(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::Bool) { + return reg->getbool(); + } else if (type == qMetaTypeId<QVariant>()) { + return reg->getvariantptr()->toBool(); + } else { + if (ok) *ok = false; + return false; + } +} + +inline static QUrl toUrl(Register *reg, int type, QmlContextPrivate *context, bool *ok = 0) +{ + if (ok) *ok = true; + + QUrl base; + if (type == qMetaTypeId<QVariant>()) { + QVariant *var = reg->getvariantptr(); + int vt = var->type(); + if (vt == QVariant::Url) { + base = var->toUrl(); + } else if (vt == QVariant::ByteArray) { + base = QUrl(QString::fromUtf8(var->toByteArray())); + } else if (vt == QVariant::String) { + base = QUrl(var->toString()); + } else { + if (ok) *ok = false; + return QUrl(); + } + } else if (type == QMetaType::QString) { + base = QUrl(*reg->getstringptr()); + } else { + if (ok) *ok = false; + return QUrl(); + } + + if (!base.isEmpty() && base.isRelative()) + return context->url.resolved(base); + else + return base; +} + static QObject *variantToQObject(const QVariant &value, bool *ok) { - *ok = false; - Q_UNUSED(value); - return 0; + if (ok) *ok = true; + + if (value.userType() == QMetaType::QObjectStar) { + return qvariant_cast<QObject*>(value); + } else { + if (ok) *ok = false; + return 0; + } } -static QmlPropertyCache::Data *findproperty(QObject *obj, - const QScriptDeclarativeClass::Identifier &name, - QmlEnginePrivate *enginePriv, - QmlPropertyCache::Data &local) +QmlPropertyCache::Data * +QmlCompiledBindingsPrivate::findproperty(QObject *obj, + const QScriptDeclarativeClass::Identifier &name, + QmlEnginePrivate *enginePriv, + QmlPropertyCache::Data &local) { QmlPropertyCache *cache = 0; QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); @@ -429,21 +837,22 @@ static QmlPropertyCache::Data *findproperty(QObject *obj, return property; } -static bool findproperty(QObject *obj, Register *output, - QmlEnginePrivate *enginePriv, - QmlBindingVME::Config *config, int subIdx, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) +bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, + QmlEnginePrivate *enginePriv, + int subIdx, const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { - if (!obj) + if (!obj) { + output->setUndefined(); return false; + } QmlPropertyCache::Data local; QmlPropertyCache::Data *property = findproperty(obj, name, enginePriv, local); if (property) { if (subIdx != -1) - subscribe(obj, property->notifyIndex, subIdx, config); + subscribe(obj, property->notifyIndex, subIdx); if (property->flags & QmlPropertyCache::Data::IsQObjectDerived) { void *args[] = { output->typeDataPtr(), 0 }; @@ -460,15 +869,16 @@ static bool findproperty(QObject *obj, Register *output, } else { bool ok; output->setQObject(variantToQObject(v, &ok)); - if (!ok) return false; - output->settype(QMetaType::QObjectStar); + if (!ok) + output->setUndefined(); + else + output->settype(QMetaType::QObjectStar); } } else { - if (!isTerminal) - return false; - - if (property->propType == QMetaType::QReal) { + if (!isTerminal) { + output->setUndefined(); + } else if (property->propType == QMetaType::QReal) { void *args[] = { output->typeDataPtr(), 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); output->settype(QMetaType::QReal); @@ -490,32 +900,20 @@ static bool findproperty(QObject *obj, Register *output, QVariant(obj->metaObject()->property(property->coreIndex).read(obj)); output->settype(qMetaTypeId<QVariant>()); } - } return true; } else { + output->setUndefined(); return false; } } -static bool findproperty(Register *input, - Register *output, - QmlEnginePrivate *enginePriv, - QmlBindingVME::Config *config, int subIdx, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) -{ - return findproperty(input->getQObject(), output, enginePriv, - config, subIdx, name, isTerminal); -} - -static bool findgeneric(Register *output, // value output - QmlBindingVME::Config *config, - int subIdx, // Subscription index in config - QmlContextPrivate *context, // Context to search in - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) +void QmlCompiledBindingsPrivate::findgeneric(Register *output, + int subIdx, + QmlContextPrivate *context, + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(context->engine); @@ -527,8 +925,7 @@ static bool findgeneric(Register *output, // val if (contextPropertyIndex != -1) { if (subIdx != -1) - subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, - subIdx, config); + subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, subIdx); if (contextPropertyIndex < context->idValueCount) { output->setQObject(context->idValues[contextPropertyIndex]); @@ -541,26 +938,26 @@ static bool findgeneric(Register *output, // val } else { bool ok; output->setQObject(variantToQObject(value, &ok)); - if (!ok) return false; - output->settype(QMetaType::QObjectStar); + if (!ok) { output->setUndefined(); } + else { output->settype(QMetaType::QObjectStar); } + return; } } - return true; + return; } for (int ii = 0; ii < context->scripts.count(); ++ii) { QScriptValue function = QScriptDeclarativeClass::function(context->scripts.at(ii), name); if (function.isValid()) { qFatal("Binding optimizer resolved name to QScript method"); - return false; } } if (QObject *root = context->defaultObjects.isEmpty()?0:context->defaultObjects.first()) { - if (findproperty(root, output, enginePriv, config, subIdx, name, isTerminal)) - return true; + if (findproperty(root, output, enginePriv, subIdx, name, isTerminal)) + return; } @@ -571,106 +968,48 @@ static bool findgeneric(Register *output, // val } } - return false; -} - - -// Conversion functions - these MUST match the QtScript expression path -inline static qreal toReal(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return reg->getqreal(); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toReal(); - } else { - if (ok) *ok = false; - return 0; - } + output->setUndefined(); } -inline static QString toString(Register *reg, int type, bool *ok = 0) +void QmlCompiledBindingsPrivate::init() { - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return QString::number(reg->getqreal()); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toString(); - } else if (type == QMetaType::QString) { - return *reg->getstringptr(); - } else { - if (ok) *ok = false; - return QString(); - } -} - -inline static bool toBool(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; + Program *program = (Program *)programData; + if (program->subscriptions) + subscriptions = new QmlCompiledBindingsPrivate::Subscription[program->subscriptions]; + if (program->identifiers) + identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; - if (type == QMetaType::Bool) { - return reg->getbool(); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toBool(); - } else { - if (ok) *ok = false; - return false; - } + m_signalTable = (quint32 *)(program->data() + program->signalTableOffset); + m_bindings = new QmlCompiledBindingsPrivate::Binding[program->bindings]; } -inline static QUrl toUrl(Register *reg, int type, QmlContextPrivate *context, bool *ok = 0) +static void throwException(int id, QmlDelayedError *error, + Program *program, QmlContextPrivate *context, + const QString &description = QString()) { - if (ok) *ok = true; - - QUrl base; - if (type == qMetaTypeId<QVariant>()) { - QVariant *var = reg->getvariantptr(); - int vt = var->type(); - if (vt == QVariant::Url) { - base = var->toUrl(); - } else if (vt == QVariant::ByteArray) { - base = QUrl(QString::fromUtf8(var->toByteArray())); - } else if (vt == QVariant::String) { - base = QUrl(var->toString()); - } else { - if (ok) *ok = false; - return QUrl(); - } - } else if (type == QMetaType::QString) { - base = QUrl(*reg->getstringptr()); + error->error.setUrl(context->url); + if (description.isEmpty()) + error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object")); + else + error->error.setDescription(description); + if (id != 0xFF) { + quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); + error->error.setLine((e >> 32) & 0xFFFFFFFF); + error->error.setColumn(e & 0xFFFFFFFF); } else { - if (ok) *ok = false; - return QUrl(); + error->error.setLine(-1); + error->error.setColumn(-1); } - - if (!base.isEmpty() && base.isRelative()) - return context->url.resolved(base); - else - return base; + if (!context->engine || !error->addError(QmlEnginePrivate::get(context->engine))) + qWarning() << error->error; } -/*! -Returns the signal/binding table. -*/ -void QmlBindingVME::init(const char *programData, Config *config, - quint32 **sigTable, quint32 *bindingCount) +void QmlCompiledBindingsPrivate::run(int instrIndex, + QmlContextPrivate *context, QmlDelayedError *error, + QObject *scope, QObject *output) { - Program *program = (Program *)programData; - if (program->subscriptions) - config->subscriptions = new Config::Subscription[program->subscriptions]; - if (program->identifiers) - config->identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; + error->removeError(); - *sigTable = (quint32 *)(program->data() + program->signalTableOffset); - *bindingCount = program->bindings; -} - -void QmlBindingVME::run(const char *programData, int instrIndex, - Config *config, QmlContextPrivate *context, - QObject **scopes, QObject **outputs) -{ Register registers[32]; int storeFlags = 0; @@ -687,18 +1026,16 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::SubscribeId: - case Instr::Subscribe: - { - QObject *o = registers[instr->subscribe.reg].getQObject(); - int notifyIndex = instr->subscribe.index; - - if (instr->common.type == Instr::SubscribeId) { - o = QmlContextPrivate::get(context); - notifyIndex += context->notifyIndex; - } + subscribeId(context, instr->subscribe.index, instr->subscribe.offset); + break; - subscribe(o, instr->subscribe.index, instr->subscribe.offset, config); - } + case Instr::Subscribe: + { + QObject *o = 0; + const Register &object = registers[instr->subscribe.reg]; + if (!object.isUndefined()) o = object.getQObject(); + subscribe(o, instr->subscribe.index, instr->subscribe.offset); + } break; case Instr::LoadId: @@ -706,7 +1043,7 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::LoadScope: - registers[instr->load.reg].setQObject(scopes[instr->load.index]); + registers[instr->load.reg].setQObject(scope); break; case Instr::LoadRoot: @@ -714,20 +1051,44 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::LoadAttached: - { - QObject *o = qmlAttachedPropertiesObjectById(instr->attached.index, - registers[instr->attached.reg].getQObject(), - true); - registers[instr->attached.output].setQObject(o); + { + const Register &input = registers[instr->attached.reg]; + Register &output = registers[instr->attached.output]; + if (input.isUndefined()) { + throwException(instr->attached.exceptionId, error, program, context); + return; } + + QObject *object = registers[instr->attached.reg].getQObject(); + if (!object) { + output.setUndefined(); + } else { + QObject *attached = + qmlAttachedPropertiesObjectById(instr->attached.index, + registers[instr->attached.reg].getQObject(), + true); + Q_ASSERT(attached); + output.setQObject(attached); + } + } break; case Instr::ConvertIntToReal: - registers[instr->unaryop.output].setqreal(qreal(registers[instr->unaryop.src].getint())); + { + const Register &input = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (input.isUndefined()) output.setUndefined(); + else output.setqreal(qreal(input.getint())); + } break; case Instr::ConvertRealToInt: - registers[instr->unaryop.output].setint(int(registers[instr->unaryop.src].getqreal())); + { + const Register &input = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (input.isUndefined()) output.setUndefined(); + else output.setint(int(input.getqreal())); + } break; case Instr::Real: @@ -743,74 +1104,160 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::String: - new (registers[instr->bool_value.reg].getstringptr()) + { + Register &output = registers[instr->string_value.reg]; + new (output.getstringptr()) QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); + output.settype(QMetaType::QString); + } break; case Instr::AddReal: - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.src1].getqreal() + - registers[instr->binaryop.src2].getqreal()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setqreal(lhs.getqreal() + rhs.getqreal()); + } break; case Instr::AddInt: - registers[instr->binaryop.output].setint(registers[instr->binaryop.src1].getint() + - registers[instr->binaryop.src2].getint()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setint(lhs.getint() + rhs.getint()); + } break; case Instr::AddString: - new (registers[instr->binaryop.output].getstringptr()) - QString(*registers[instr->binaryop.src1].getstringptr() + - *registers[instr->binaryop.src2].getstringptr()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() && rhs.isUndefined()) { output.setNaN(); } + else { + if (lhs.isUndefined()) + new (output.getstringptr()) + QString(QLatin1String("undefined") + *registers[instr->binaryop.src2].getstringptr()); + else if (rhs.isUndefined()) + new (output.getstringptr()) + QString(*registers[instr->binaryop.src1].getstringptr() + QLatin1String("undefined")); + else + new (output.getstringptr()) + QString(*registers[instr->binaryop.src1].getstringptr() + + *registers[instr->binaryop.src2].getstringptr()); + output.settype(QMetaType::QString); + } + } break; case Instr::MinusReal: - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.src1].getqreal() - - registers[instr->binaryop.src2].getqreal()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setqreal(lhs.getqreal() - rhs.getqreal()); + } break; case Instr::MinusInt: - registers[instr->binaryop.output].setint(registers[instr->binaryop.src1].getint() - - registers[instr->binaryop.src2].getint()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setint(lhs.getint() - rhs.getint()); + } break; case Instr::CompareReal: - registers[instr->binaryop.output].setbool(registers[instr->binaryop.src1].getqreal() == - registers[instr->binaryop.src2].getqreal()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined()); + else output.setbool(lhs.getqreal() == rhs.getqreal()); + } break; case Instr::CompareString: - registers[instr->binaryop.output].setbool(*registers[instr->binaryop.src1].getstringptr() == - *registers[instr->binaryop.src2].getstringptr()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined()); + else output.setbool(*lhs.getstringptr() == *rhs.getstringptr()); + } break; case Instr::NotCompareReal: - registers[instr->binaryop.output].setbool(registers[instr->binaryop.src1].getqreal() != - registers[instr->binaryop.src2].getqreal()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined()); + else output.setbool(lhs.getqreal() != rhs.getqreal()); + } break; case Instr::NotCompareString: - registers[instr->binaryop.output].setbool(*registers[instr->binaryop.src1].getstringptr() != - *registers[instr->binaryop.src2].getstringptr()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined()); + else output.setbool(*lhs.getstringptr() != *rhs.getstringptr()); + } break; case Instr::GreaterThanReal: - registers[instr->binaryop.output].setbool(registers[instr->binaryop.src1].getqreal() > - registers[instr->binaryop.src2].getqreal()); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(false); + else output.setbool(lhs.getqreal() > rhs.getqreal()); + } break; + case Instr::MaxReal: - registers[instr->binaryop.output].setqreal(qMax(registers[instr->binaryop.src1].getqreal(), - registers[instr->binaryop.src2].getqreal())); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setqreal(qMax(lhs.getqreal(), rhs.getqreal())); + } break; + case Instr::MinReal: - registers[instr->binaryop.output].setqreal(qMin(registers[instr->binaryop.src1].getqreal(), - registers[instr->binaryop.src2].getqreal())); + { + const Register &lhs = registers[instr->binaryop.src1]; + const Register &rhs = registers[instr->binaryop.src2]; + Register &output = registers[instr->binaryop.output]; + if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); + else output.setqreal(qMin(lhs.getqreal(), rhs.getqreal())); + } break; + case Instr::NewString: - new (registers[instr->construct.reg].typeMemory()) QString; + { + Register &output = registers[instr->construct.reg]; + new (output.getstringptr()) QString; + output.settype(QMetaType::QString); + } break; case Instr::NewUrl: - new (registers[instr->construct.reg].typeMemory()) QUrl; + { + Register &output = registers[instr->construct.reg]; + new (output.geturlptr()) QUrl; + output.settype(QMetaType::QUrl); + } break; case Instr::CleanupString: @@ -822,25 +1269,39 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::Fetch: - { - QObject *object = registers[instr->fetch.objectReg].getQObject(); - if (!object) { - qWarning() << "ERROR - Fetch"; - return; - } - void *argv[] = { registers[instr->fetch.output].typeDataPtr(), 0 }; + { + const Register &input = registers[instr->fetch.objectReg]; + Register &output = registers[instr->fetch.output]; + + if (input.isUndefined()) { + throwException(instr->fetch.exceptionId, error, program, context); + return; + } + + QObject *object = input.getQObject(); + if (!object) { + output.setUndefined(); + } else { + void *argv[] = { output.typeDataPtr(), 0 }; QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); } + } break; case Instr::Store: - { - int status = -1; - void *argv[] = { registers[instr->store.reg].typeDataPtr(), - 0, &status, &storeFlags }; - QMetaObject::metacall(outputs[instr->store.output], QMetaObject::WriteProperty, - instr->store.index, argv); + { + Register &data = registers[instr->store.reg]; + if (data.isUndefined()) { + throwException(instr->store.exceptionId, error, program, context, + QLatin1String("Unable to assign undefined value")); + return; } + + int status = -1; + void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; + QMetaObject::metacall(output, QMetaObject::WriteProperty, + instr->store.index, argv); + } break; case Instr::Copy: @@ -856,14 +1317,13 @@ void QmlBindingVME::run(const char *programData, int instrIndex, return; case Instr::InitString: - if (!config->identifiers[instr->initstring.offset].identifier) { + if (!identifiers[instr->initstring.offset].identifier) { quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); QString str = QString::fromRawData(strdata, len); - config->identifiers[instr->initstring.offset] = - engine->objectClass->createPersistentIdentifier(str); + identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); } break; @@ -872,68 +1332,81 @@ void QmlBindingVME::run(const char *programData, int instrIndex, // We start the search in the parent context, as we know that the // name is not present in the current context or it would have been // found during the static compile - if (!findgeneric(registers + instr->find.reg, config, instr->find.subscribeIndex, - QmlContextPrivate::get(context->parent), - config->identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindGenericTerminal)) { - qWarning() << "ERROR - FindGeneric*"; - return; - } + findgeneric(registers + instr->find.reg, instr->find.subscribeIndex, + QmlContextPrivate::get(context->parent), + identifiers[instr->find.name].identifier, + instr->common.type == Instr::FindGenericTerminal); break; case Instr::FindPropertyTerminal: case Instr::FindProperty: - if (!findproperty(registers + instr->find.src, registers + instr->find.reg, - QmlEnginePrivate::get(context->engine), - config, instr->find.subscribeIndex, - config->identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindPropertyTerminal)) { - qWarning() << "ERROR - FindProperty*"; + { + const Register &object = registers[instr->find.src]; + if (object.isUndefined()) { + throwException(instr->find.exceptionId, error, program, context); return; } + + findproperty(object.getQObject(), registers + instr->find.reg, + QmlEnginePrivate::get(context->engine), + instr->find.subscribeIndex, identifiers[instr->find.name].identifier, + instr->common.type == Instr::FindPropertyTerminal); + } break; case Instr::CleanupGeneric: - { - int type = registers[instr->cleanup.reg].gettype(); - if (type == qMetaTypeId<QVariant>()) { - registers[instr->cleanup.reg].getvariantptr()->~QVariant(); - } else if (type == QMetaType::QString) { - registers[instr->cleanup.reg].getstringptr()->~QString(); - } else if (type == QMetaType::QUrl) { - registers[instr->cleanup.reg].geturlptr()->~QUrl(); - } + { + int type = registers[instr->cleanup.reg].gettype(); + if (type == qMetaTypeId<QVariant>()) { + registers[instr->cleanup.reg].getvariantptr()->~QVariant(); + } else if (type == QMetaType::QString) { + registers[instr->cleanup.reg].getstringptr()->~QString(); + } else if (type == QMetaType::QUrl) { + registers[instr->cleanup.reg].geturlptr()->~QUrl(); } + } break; case Instr::ConvertGenericToReal: - { - int type = registers[instr->unaryop.src].gettype(); - registers[instr->unaryop.output].setqreal(toReal(registers + instr->unaryop.src, type)); - } + { + Register &output = registers[instr->unaryop.output]; + Register &input = registers[instr->unaryop.src]; + bool ok = true; + output.setqreal(toReal(&input, input.gettype(), &ok)); + if (!ok) output.setUndefined(); + } break; case Instr::ConvertGenericToBool: - { - int type = registers[instr->unaryop.src].gettype(); - registers[instr->unaryop.output].setbool(toBool(registers + instr->unaryop.src, type)); - } + { + Register &output = registers[instr->unaryop.output]; + Register &input = registers[instr->unaryop.src]; + bool ok = true; + output.setbool(toBool(&input, input.gettype(), &ok)); + if (!ok) output.setUndefined(); + } break; case Instr::ConvertGenericToString: - { - int type = registers[instr->unaryop.src].gettype(); - void *regPtr = registers[instr->unaryop.output].typeDataPtr(); - new (regPtr) QString(toString(registers + instr->unaryop.src, type)); - } + { + Register &output = registers[instr->unaryop.output]; + Register &input = registers[instr->unaryop.src]; + bool ok = true; + QString str = toString(&input, input.gettype(), &ok); + if (ok) { new (output.getstringptr()) QString(str); output.settype(QMetaType::QString); } + else { output.setUndefined(); } + } break; case Instr::ConvertGenericToUrl: - { - int type = registers[instr->unaryop.src].gettype(); - void *regPtr = registers[instr->unaryop.output].typeDataPtr(); - new (regPtr) QUrl(toUrl(registers + instr->unaryop.src, type, context)); - } + { + Register &output = registers[instr->unaryop.output]; + Register &input = registers[instr->unaryop.src]; + bool ok = true; + QUrl url = toUrl(&input, input.gettype(), context, &ok); + if (ok) { new (output.geturlptr()) QUrl(url); output.settype(QMetaType::QUrl); } + else { output.setUndefined(); } + } break; default: @@ -945,9 +1418,9 @@ void QmlBindingVME::run(const char *programData, int instrIndex, } } -void QmlBindingVME::dump(const char *programData) +void QmlBindingCompiler::dump(const QByteArray &programData) { - const Program *program = (const Program *)programData; + const Program *program = (const Program *)programData.constData(); qWarning() << "Program.bindings:" << program->bindings; qWarning() << "Program.dataLength:" << program->dataLength; @@ -1110,6 +1583,7 @@ void QmlBindingCompilerPrivate::resetInstanceState() registers = 0; registerCleanups.clear(); data = committed.data; + exceptions = committed.exceptions; usedSubscriptionIds.clear(); subscriptionSet.clear(); subscriptionIds = committed.subscriptionIds; @@ -1130,6 +1604,7 @@ int QmlBindingCompilerPrivate::commitCompile() committed.dependencies << usedSubscriptionIds; committed.bytecode << bytecode; committed.data = data; + committed.exceptions = exceptions; committed.subscriptionIds = subscriptionIds; committed.registeredStrings = registeredStrings; return rv; @@ -1193,6 +1668,7 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node) instr.store.output = 0; instr.store.index = destination->index; instr.store.reg = convertReg; + instr.store.exceptionId = exceptionId(node->expressionCast()); bytecode << instr; if (destination->type == QVariant::String) { @@ -1247,6 +1723,7 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node) instr.store.output = 0; instr.store.index = destination->index; instr.store.reg = type.reg; + instr.store.exceptionId = exceptionId(node->expressionCast()); bytecode << instr; releaseReg(type.reg); @@ -1294,7 +1771,8 @@ bool QmlBindingCompilerPrivate::tryName(QmlJS::AST::Node *node) bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) { QStringList nameParts; - if (!buildName(nameParts, node)) + QList<AST::ExpressionNode *> nameNodes; + if (!buildName(nameParts, node, &nameNodes)) return false; int reg = acquireReg(); @@ -1347,6 +1825,7 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) attach.attached.output = reg; attach.attached.reg = reg; attach.attached.index = attachType->index(); + attach.attached.exceptionId = exceptionId(nameNodes.at(ii)); bytecode << attach; subscribeName << contextName(); @@ -1414,7 +1893,7 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) subscribeName << contextName(); subscribeName << name; - fetch(type, context->metaObject(), reg, d0Idx, subscribeName); + fetch(type, context->metaObject(), reg, d0Idx, subscribeName, nameNodes.at(ii)); } else if(d1Idx != -1) { Instr instr; instr.common.type = Instr::LoadRoot; @@ -1425,7 +1904,7 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) subscribeName << QLatin1String("$$$ROOT"); subscribeName << name; - fetch(type, component->metaObject(), reg, d1Idx, subscribeName); + fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii)); } else { Instr find; if (nameParts.count() == 1) @@ -1436,6 +1915,7 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) find.find.reg = reg; find.find.src = -1; find.find.name = registerString(name); + find.find.exceptionId = exceptionId(nameNodes.at(ii)); subscribeName << QString(QLatin1String("$$$Generic_") + name); if (subscription(subscribeName, &type)) @@ -1484,7 +1964,7 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) if (absType || (wasAttachedObject && idx != -1) || (mo && mo->property(idx).isFinal())) { absType = 0; - fetch(type, mo, reg, idx, subscribeName); + fetch(type, mo, reg, idx, subscribeName, nameNodes.at(ii)); if (type.type == -1) return false; } else { @@ -1498,6 +1978,8 @@ bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type) prop.find.reg = reg; prop.find.src = reg; prop.find.name = registerString(name); + prop.find.exceptionId = exceptionId(nameNodes.at(ii)); + if (subscription(subscribeName, &type)) prop.find.subscribeIndex = subscriptionIndex(subscribeName); else @@ -1920,18 +2402,21 @@ bool QmlBindingCompilerPrivate::parseMethod(QmlJS::AST::Node *node, Result &resu } bool QmlBindingCompilerPrivate::buildName(QStringList &name, - QmlJS::AST::Node *node) + QmlJS::AST::Node *node, + QList<QmlJS::AST::ExpressionNode *> *nodes) { if (node->kind == AST::Node::Kind_IdentifierExpression) { name << static_cast<AST::IdentifierExpression*>(node)->name->asString(); + if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node); } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { AST::FieldMemberExpression *expr = static_cast<AST::FieldMemberExpression *>(node); - if (!buildName(name, expr->base)) + if (!buildName(name, expr->base, nodes)) return false; name << expr->name->asString(); + if (nodes) *nodes << expr; } else { return false; } @@ -1940,7 +2425,8 @@ bool QmlBindingCompilerPrivate::buildName(QStringList &name, } -bool QmlBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg, int idx, const QStringList &subName) +bool QmlBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg, + int idx, const QStringList &subName, QmlJS::AST::ExpressionNode *node) { QMetaProperty prop = mo->property(idx); rv.metaObject = 0; @@ -1960,6 +2446,7 @@ bool QmlBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg fetch.fetch.objectReg = reg; fetch.fetch.index = idx; fetch.fetch.output = reg; + fetch.fetch.exceptionId = exceptionId(node); rv.type = prop.userType(); rv.metaObject = QmlMetaType::metaObjectForType(rv.type); @@ -2122,6 +2609,19 @@ bool QmlBindingCompilerPrivate::subscriptionNeutral(const QSet<QString> &base, return difflhs.isEmpty(); } +quint8 QmlBindingCompilerPrivate::exceptionId(QmlJS::AST::ExpressionNode *n) +{ + quint8 rv = 0xFF; + if (n && exceptions.count() < 0xFF) { + rv = (quint8)exceptions.count(); + QmlJS::AST::SourceLocation l = n->firstSourceLocation(); + quint64 e = l.startLine; + e <<= 32; + e |= l.startColumn; + exceptions.append(e); + } + return rv; +} QmlBindingCompiler::QmlBindingCompiler() : d(new QmlBindingCompilerPrivate) @@ -2144,8 +2644,7 @@ bool QmlBindingCompiler::isValid() const /* -1 on failure, otherwise the binding index to use. */ -int QmlBindingCompiler::compile(const QmlBasicScript::Expression &expression, - QmlEnginePrivate *engine) +int QmlBindingCompiler::compile(const Expression &expression, QmlEnginePrivate *engine) { if (!expression.expression.asAST()) return false; @@ -2188,6 +2687,14 @@ QByteArray QmlBindingCompilerPrivate::buildSignalTable() const return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32)); } +QByteArray QmlBindingCompilerPrivate::buildExceptionData() const +{ + QByteArray rv; + rv.resize(committed.exceptions.count() * sizeof(quint64)); + ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); + return rv; +} + /* Returns the compiled program. */ @@ -2214,6 +2721,9 @@ QByteArray QmlBindingCompiler::program() const while (data.count() % 4) data.append('\0'); prog.signalTableOffset = data.count(); data += d->buildSignalTable(); + while (data.count() % 4) data.append('\0'); + prog.exceptionDataOffset = data.count(); + data += d->buildExceptionData(); prog.dataLength = 4 * ((data.size() + 3) / 4); prog.subscriptions = d->committed.subscriptionIds.count(); @@ -2235,5 +2745,5 @@ QByteArray QmlBindingCompiler::program() const } -QT_END_NAMESPACE +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlcompiledbindings_p.h index c4b436d..1d8fac4 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlcompiledbindings_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QMLBASICSCRIPT_P_H -#define QMLBASICSCRIPT_P_H +#ifndef QMLBINDINGOPTIMIZATIONS_P_H +#define QMLBINDINGOPTIMIZATIONS_P_H // // W A R N I N G @@ -53,34 +53,22 @@ // We mean it. // -#include "qmlparser_p.h" -#include "qmlengine_p.h" - -#include <QtCore/QList> -#include <QtCore/QByteArray> -#include <QtCore/QVariant> +#include "qmlexpression_p.h" +#include "qmlbinding.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QmlRefCount; -class QmlContext; -class QmlBasicScriptPrivate; -class QmlBasicScriptNodeCache; -class QmlBasicScript +class QmlBindingCompilerPrivate; +class QmlBindingCompiler { public: - QmlBasicScript(); - ~QmlBasicScript(); - - void load(const char *, QmlRefCount * = 0); - - // Always 4-byte aligned - const char *compileData() const; - unsigned int compileDataSize() const; + QmlBindingCompiler(); + ~QmlBindingCompiler(); - QByteArray expression() const; + // Returns true if bindings were compiled + bool isValid() const; struct Expression { @@ -92,26 +80,37 @@ public: QmlEnginePrivate::Imports imports; }; - bool compile(const Expression &); - bool isValid() const; + // -1 on failure, otherwise the binding index to use + int compile(const Expression &, QmlEnginePrivate *); - void clear(); + // Returns the compiled program + QByteArray program() const; - void dump(); + static void dump(const QByteArray &); +private: + QmlBindingCompilerPrivate *d; +}; - QVariant run(QmlContext *, QObject *); +class QmlCompiledBindingsPrivate; +class QmlCompiledBindings : public QObject, public QmlAbstractExpression, public QmlRefCount +{ +public: + QmlCompiledBindings(const char *program, QmlContext *context); + virtual ~QmlCompiledBindings(); - bool isSingleIdFetch() const; - int singleIdFetchIndex() const; + QmlAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); + +protected: + int qt_metacall(QMetaObject::Call, int, void **); private: - int flags; - QmlBasicScriptPrivate *d; - QmlRefCount *rc; + Q_DISABLE_COPY(QmlCompiledBindings); + Q_DECLARE_PRIVATE(QmlCompiledBindings); }; QT_END_NAMESPACE QT_END_HEADER -#endif // QMLBASICSCRIPT_P_H +#endif // QMLBINDINGOPTIMIZATIONS_P_H + diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 4ee59b3..bb7abf3 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -47,7 +47,6 @@ #include "qmlpropertyvaluesource.h" #include "qmlcomponent.h" #include "qmetaobjectbuilder_p.h" -#include "qmlbasicscript_p.h" #include "qmlstringconverters_p.h" #include "qmlengine_p.h" #include "qmlengine.h" @@ -65,7 +64,7 @@ #include "qmlglobal_p.h" #include "qmlscriptparser_p.h" #include "qmlbinding.h" -#include "qmlbindingvme_p.h" +#include "qmlcompiledbindings_p.h" #include <qfxperf_p_p.h> @@ -258,26 +257,30 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, break; case QVariant::Color: { - QColor c = QmlStringConverters::colorFromString(string); - if (!c.isValid()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: color expected")); + bool ok; + QmlStringConverters::colorFromString(string, &ok); + if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: color expected")); } break; case QVariant::Date: { - QDate d = QDate::fromString(string, Qt::ISODate); - if (!d.isValid()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: date expected")); + bool ok; + QmlStringConverters::dateFromString(string, &ok); + if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: date expected")); } break; case QVariant::Time: { - QTime time = QTime::fromString(string, Qt::ISODate); - if (!time.isValid()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: time expected")); + bool ok; + QmlStringConverters::timeFromString(string, &ok); + if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: time expected")); } break; case QVariant::DateTime: { - QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); - if (!dateTime.isValid()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: datetime expected")); + bool ok; + QmlStringConverters::dateTimeFromString(string, &ok); + if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: datetime expected")); } break; case QVariant::Point: @@ -312,7 +315,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::Vector3D: { bool ok; - QVector3D point = QmlStringConverters::vector3DFromString(string, &ok); + QmlStringConverters::vector3DFromString(string, &ok); if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: 3D vector expected")); } break; @@ -418,7 +421,7 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, break; case QVariant::Date: { - QDate d = QDate::fromString(string, Qt::ISODate); + QDate d = QmlStringConverters::dateFromString(string); instr.type = QmlInstruction::StoreDate; instr.storeDate.propertyIndex = prop.propertyIndex(); instr.storeDate.value = d.toJulianDay(); @@ -426,7 +429,7 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, break; case QVariant::Time: { - QTime time = QTime::fromString(string, Qt::ISODate); + QTime time = QmlStringConverters::timeFromString(string); int data[] = { time.hour(), time.minute(), time.second(), time.msec() }; int index = output->indexForInt(data, 4); @@ -437,7 +440,7 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, break; case QVariant::DateTime: { - QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); + QDateTime dateTime = QmlStringConverters::dateTimeFromString(string); int data[] = { dateTime.date().toJulianDay(), dateTime.time().hour(), dateTime.time().minute(), @@ -1610,7 +1613,7 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop, store.assignValueSource.property = genPropertyData(prop); store.assignValueSource.owner = 0; } - QmlType *valueType = QmlMetaType::qmlType(v->object->metatype); + QmlType *valueType = toQmlType(v->object); store.assignValueSource.castValue = valueType->propertyValueSourceCast(); output->bytecode << store; @@ -1627,7 +1630,7 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop, store.assignValueInterceptor.property = genPropertyData(prop); store.assignValueInterceptor.owner = 0; } - QmlType *valueType = QmlMetaType::qmlType(v->object->metatype); + QmlType *valueType = toQmlType(v->object); store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast(); output->bytecode << store; @@ -1995,7 +1998,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, bool isPropertyValue = false; // Will be true if the assigned type inherits QmlPropertyValueInterceptor bool isPropertyInterceptor = false; - if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) { + if (QmlType *valueType = toQmlType(v->object)) { isPropertyValue = valueType->propertyValueSourceCast() != -1; isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1; } @@ -2388,7 +2391,6 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const Object::DynamicSlot &s = obj->dynamicSlots.at(ii); const QString &funcScript = funcScripts.at(ii); QmlVMEMetaData::MethodData *data = ((QmlVMEMetaData *)dynamicData.data())->methodData() + ii; @@ -2559,23 +2561,6 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, } QmlInstruction store; - - QmlBasicScript bs; - if (ref.dataType == BindingReference::BasicScript) - bs.load(ref.compiledData.constData() + sizeof(quint32)); - - if (bs.isSingleIdFetch()) { - int idIndex = bs.singleIdFetchIndex(); - QmlParser::Object *idObj = compileState.idIndexes.value(idIndex); - if (canCoerce(prop->type, idObj)) { - store.type = QmlInstruction::StoreIdOptBinding; - store.assignIdOptBinding.id = idIndex; - store.assignIdOptBinding.property = prop->index; - output->bytecode << store; - return; - } - } - store.type = QmlInstruction::StoreBinding; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; @@ -2629,7 +2614,7 @@ bool QmlCompiler::completeComponentBuild() COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases)); } - QmlBasicScript::Expression expr; + QmlBindingCompiler::Expression expr; expr.component = compileState.root; expr.ids = compileState.ids; @@ -2638,15 +2623,12 @@ bool QmlCompiler::completeComponentBuild() for (QHash<QmlParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) { BindingReference &binding = *iter; - QmlBasicScript bs; expr.context = binding.bindingContext.object; expr.property = binding.property; expr.expression = binding.expression; expr.imports = unit->imports; - bs.compile(expr); - - if (qmlExperimental() && (!bs.isValid() || !bs.isSingleIdFetch())) { + if (qmlExperimental()) { int index = bindingCompiler.compile(expr, QmlEnginePrivate::get(engine)); if (index != -1) { qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript()); @@ -2659,55 +2641,42 @@ bool QmlCompiler::completeComponentBuild() } } - quint32 type; - if (bs.isValid()) { - binding.compiledData = - QByteArray(bs.compileData(), bs.compileDataSize()); - type = QmlExpressionPrivate::BasicScriptEngineData; - binding.dataType = BindingReference::BasicScript; + binding.dataType = BindingReference::QtScript; - componentStat.optimizedBindings++; - } else { - type = QmlExpressionPrivate::PreTransformedQtScriptData; - binding.dataType = BindingReference::QtScript; - - // Pre-rewrite the expression - QString expression = binding.expression.asScript(); - - // ### Optimize - QmlRewrite::SharedBindingTester sharableTest; - bool isSharable = sharableTest.isSharable(expression); - - QmlRewrite::RewriteBinding rewriteBinding; - expression = rewriteBinding(expression); - - quint32 length = expression.length(); - quint32 pc; - - if (isSharable) { - pc = output->cachedClosures.count(); - pc |= 0x80000000; - output->cachedClosures.append(0); - } else { - pc = output->cachedPrograms.length(); - output->cachedPrograms.append(0); - } + // Pre-rewrite the expression + QString expression = binding.expression.asScript(); - binding.compiledData = - QByteArray((const char *)&pc, sizeof(quint32)) + - QByteArray((const char *)&length, sizeof(quint32)) + - QByteArray((const char *)expression.constData(), - expression.length() * sizeof(QChar)); + // ### Optimize + QmlRewrite::SharedBindingTester sharableTest; + bool isSharable = sharableTest.isSharable(expression); + + QmlRewrite::RewriteBinding rewriteBinding; + expression = rewriteBinding(expression); - componentStat.scriptBindings++; + quint32 length = expression.length(); + quint32 pc; + + if (isSharable) { + pc = output->cachedClosures.count(); + pc |= 0x80000000; + output->cachedClosures.append(0); + } else { + pc = output->cachedPrograms.length(); + output->cachedPrograms.append(0); } - binding.compiledData.prepend(QByteArray((const char *)&type, - sizeof(quint32))); + + binding.compiledData = + QByteArray((const char *)&pc, sizeof(quint32)) + + QByteArray((const char *)&length, sizeof(quint32)) + + QByteArray((const char *)expression.constData(), + expression.length() * sizeof(QChar)); + + componentStat.scriptBindings++; } if (bindingCompiler.isValid()) { compileState.compiledBindingData = bindingCompiler.program(); - QmlBindingVME::dump(compileState.compiledBindingData); + QmlBindingCompiler::dump(compileState.compiledBindingData); } saveComponentState(); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 732fbad..f3f266b 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -279,7 +279,7 @@ private: QmlParser::Property *property; QmlParser::Value *value; - enum DataType { QtScript, BasicScript, Experimental }; + enum DataType { QtScript, Experimental }; DataType dataType; int compiledIndex; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index e7ac864..0eb497d 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -45,7 +45,7 @@ #include "qmlexpression_p.h" #include "qmlengine_p.h" #include "qmlengine.h" -#include "qmlbindingoptimizations_p.h" +#include "qmlcompiledbindings_p.h" #include "qmlinfo.h" #include <qscriptengine.h> @@ -105,8 +105,12 @@ void QmlContextPrivate::destroyed(ContextGuard *guard) if (parent && QObjectPrivate::get(parent)->wasDeleted) return; - while(guard->bindings) - guard->bindings->reset(); + while(guard->bindings) { + QObject *o = guard->bindings->target; + int mi = guard->bindings->methodIndex; + guard->bindings->clear(); + if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0); + } for (int ii = 0; ii < idValueCount; ++ii) { if (&idValues[ii] == guard) { diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 7547004..bf389a0 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -88,7 +88,6 @@ private: friend class QmlEnginePrivate; friend class QmlExpression; friend class QmlExpressionPrivate; - friend class QmlBasicScript; friend class QmlContextScriptClass; friend class QmlObjectScriptClass; friend class QmlComponent; diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index e682ee2..cd7e1b6 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -76,7 +76,7 @@ class QmlExpression; class QmlExpressionPrivate; class QmlAbstractExpression; class QmlBinding_Id; -class QmlOptimizedBindings; +class QmlCompiledBindings; class Q_DECLARATIVE_EXPORT QmlContextPrivate : public QObjectPrivate { @@ -113,15 +113,27 @@ public: QmlDeclarativeData *contextObjects; + struct IdNotifier + { + inline IdNotifier(); + inline ~IdNotifier(); + + inline void clear(); + + IdNotifier *next; + IdNotifier**prev; + QObject *target; + int methodIndex; + }; + struct ContextGuard : public QmlGuard<QObject> { - ContextGuard() : priv(0), bindings(0) {} + inline ContextGuard(); + inline ContextGuard &operator=(QObject *obj); + inline virtual void objectDestroyed(QObject *); + QmlContextPrivate *priv; - QmlBinding_Id *bindings; - ContextGuard &operator=(QObject *obj) { - (QmlGuard<QObject>&)*this = obj; return *this; - } - void objectDestroyed(QObject *) { priv->destroyed(this); } + IdNotifier *bindings; }; ContextGuard *idValues; int idValueCount; @@ -136,12 +148,45 @@ public: return static_cast<QmlContext *>(context->q_func()); } - QmlOptimizedBindings *optimizedBindings; + QmlCompiledBindings *optimizedBindings; // Only used for debugging QList<QPointer<QObject> > instances; }; +QmlContextPrivate::IdNotifier::IdNotifier() +: next(0), prev(0), target(0), methodIndex(-1) +{ +} + +QmlContextPrivate::IdNotifier::~IdNotifier() +{ + clear(); +} + +void QmlContextPrivate::IdNotifier::clear() +{ + if (next) next->prev = prev; + if (prev) *prev = next; + next = 0; prev = 0; target = 0; + methodIndex = -1; +} + +QmlContextPrivate::ContextGuard::ContextGuard() +: priv(0), bindings(0) +{ +} + +QmlContextPrivate::ContextGuard &QmlContextPrivate::ContextGuard::operator=(QObject *obj) +{ + (QmlGuard<QObject>&)*this = obj; return *this; +} + +void QmlContextPrivate::ContextGuard::objectDestroyed(QObject *) +{ + priv->destroyed(this); +} + QT_END_NAMESPACE #endif // QMLCONTEXT_P_H diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 8ab3f8d..80d52ad 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -77,7 +77,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { via QtScript. */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) -: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), +: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -174,7 +174,8 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObje if (scopeObject) { QScriptClass::QueryFlags rv = - ep->objectClass->queryProperty(scopeObject, name, flags, bindContext, QmlObjectScriptClass::ImplicitObject); + ep->objectClass->queryProperty(scopeObject, name, flags, bindContext, + QmlObjectScriptClass::ImplicitObject | QmlObjectScriptClass::SkipAttachedProperties); if (rv) { lastScopeObject = scopeObject; lastContext = bindContext; @@ -184,7 +185,8 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObje for (int ii = cp->defaultObjects.count() - 1; ii >= 0; --ii) { QScriptClass::QueryFlags rv = - ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext, QmlObjectScriptClass::ImplicitObject); + ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext, + QmlObjectScriptClass::ImplicitObject | QmlObjectScriptClass::SkipAttachedProperties); if (rv) { lastDefaultObject = ii; @@ -196,7 +198,7 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObje return 0; } -QmlContextScriptClass::Value +QmlContextScriptClass::ScriptValue QmlContextScriptClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); @@ -206,6 +208,7 @@ QmlContextScriptClass::property(Object *object, const Identifier &name) QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (lastScopeObject) { @@ -214,9 +217,9 @@ QmlContextScriptClass::property(Object *object, const Identifier &name) } else if (lastData) { if (lastData->type) - return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); + return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type)); else - return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace); + return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace)); } else if (lastPropertyIndex != -1) { @@ -231,7 +234,7 @@ QmlContextScriptClass::property(Object *object, const Identifier &name) ep->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex); - return rv; + return Value(scriptEngine, rv); } else if(lastDefaultObject != -1) { // Default object property @@ -239,7 +242,7 @@ QmlContextScriptClass::property(Object *object, const Identifier &name) } else { - return lastFunction; + return Value(scriptEngine, lastFunction); } } diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index f652371..f98d44f 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -54,16 +54,13 @@ // #include "qmltypenamecache_p.h" - -#include <QtScript/qscriptclass.h> - -#include <private/qscriptdeclarativeclass_p.h> +#include "qmlscriptclass_p.h" QT_BEGIN_NAMESPACE class QmlEngine; class QmlContext; -class QmlContextScriptClass : public QScriptDeclarativeClass +class QmlContextScriptClass : public QmlScriptClass { public: QmlContextScriptClass(QmlEngine *); @@ -77,7 +74,7 @@ public: protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual Value property(Object *, const Identifier &); + virtual ScriptValue property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index b5e7c2d..b3ac1bb 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -46,7 +46,6 @@ #include "qmlcompiler_p.h" #include "qmlglobalscriptclass_p.h" #include "qml.h" -#include "qmlbasicscript_p.h" #include "qmlcontext.h" #include "qmlexpression.h" #include "qmlcomponent.h" @@ -64,6 +63,8 @@ #include "qmlglobal_p.h" #include "qmlworkerscript_p.h" #include "qmlcomponent_p.h" +#include "qmlscriptclass_p.h" +#include "qmlnetworkaccessmanagerfactory.h" #include <qfxperf_p_p.h> @@ -121,7 +122,8 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false), - networkAccessManager(0), typeManager(e), uniqueId(1) + networkAccessManager(0), networkAccessManagerFactory(0), accessManagerValid(false), + typeManager(e), uniqueId(1) { globalClass = new QmlGlobalScriptClass(&scriptEngine); fileImportPath.append(QLibraryInfo::location(QLibraryInfo::DataPath)+QDir::separator()+QLatin1String("qml")); @@ -386,34 +388,64 @@ QmlContext *QmlEngine::rootContext() } /*! - Sets the common QNetworkAccessManager, \a network, used by all QML elements - instantiated by this engine. + Sets the \a factory to use for creating QNetworkAccessManager(s). + + QNetworkAccessManager is used for all network access by QML. + By implementing a factory it is possible to create custom + QNetworkAccessManager with specialized caching, proxy and + cookie support. +*/ +void QmlEngine::setNetworkAccessManagerFactory(QmlNetworkAccessManagerFactory *factory) +{ + Q_D(QmlEngine); + d->networkAccessManagerFactory = factory; +} - If the parent of \a network is this engine, the engine takes ownership and - will delete it as needed. Otherwise, ownership remains with the caller. +/*! + Returns the current QmlNetworkAccessManagerFactory. - This method should only be called before any QmlComponents are instantiated. + \sa setNetworkAccessManagerFactory() */ -void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network) +QmlNetworkAccessManagerFactory *QmlEngine::networkAccessManagerFactory() const +{ + Q_D(const QmlEngine); + return d->networkAccessManagerFactory; +} + +void QmlEngine::namInvalidated() { Q_D(QmlEngine); - if (d->networkAccessManager && d->networkAccessManager->parent() == this) - delete d->networkAccessManager; - d->networkAccessManager = network; + d->accessManagerValid = false; } /*! - Returns the common QNetworkAccessManager used by all QML elements + Returns a common QNetworkAccessManager which can be used by any QML element instantiated by this engine. - The default implements no caching, cookiejar, etc., just a default - QNetworkAccessManager. + If a QmlNetworkAccessManagerFactory has been set and a QNetworkAccessManager + has not yet been created, the QmlNetworkAccessManagerFactory will be used + to create the QNetworkAccessManager; otherwise the returned QNetworkAccessManager + will have no proxy or cache set. + + \sa setNetworkAccessManagerFactory() */ QNetworkAccessManager *QmlEngine::networkAccessManager() const { Q_D(const QmlEngine); - if (!d->networkAccessManager) - d->networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(this)); + if (!d->accessManagerValid) { + delete d->networkAccessManagerFactory; + d->networkAccessManagerFactory = 0; + } + if (!d->networkAccessManager) { + if (d->networkAccessManagerFactory) { + connect(d->networkAccessManagerFactory, SIGNAL(invalidated()) + , this, SLOT(namInvalidated()), Qt::UniqueConnection); + d->networkAccessManager = d->networkAccessManagerFactory->create(const_cast<QmlEngine*>(this)); + } else { + d->networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(this)); + } + d->accessManagerValid = true; + } return d->networkAccessManager; } @@ -1056,9 +1088,8 @@ QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val) } } -QmlScriptClass::QmlScriptClass(QmlEngine *bindengine) -: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)), - engine(bindengine) +QmlScriptClass::QmlScriptClass(QScriptEngine *engine) +: QScriptDeclarativeClass(engine) { } diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index 7cbbcac..b9ec277 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -63,6 +63,7 @@ class QUrl; class QScriptEngine; class QScriptContext; class QNetworkAccessManager; +class QmlNetworkAccessManagerFactory; class Q_DECLARATIVE_EXPORT QmlEngine : public QObject { Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath) @@ -77,7 +78,9 @@ public: void addImportPath(const QString& dir); - void setNetworkAccessManager(QNetworkAccessManager *); + void setNetworkAccessManagerFactory(QmlNetworkAccessManagerFactory *); + QmlNetworkAccessManagerFactory *networkAccessManagerFactory() const; + QNetworkAccessManager *networkAccessManager() const; void setOfflineStoragePath(const QString& dir); @@ -92,6 +95,9 @@ public: Q_SIGNALS: void quit (); +private Q_SLOTS: + void namInvalidated(); + private: Q_DECLARE_PRIVATE(QmlEngine) }; diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 2f177a2..6f62b40 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -92,6 +92,7 @@ class QmlValueTypeScriptClass; class QScriptEngineDebugger; class QNetworkReply; class QNetworkAccessManager; +class QmlNetworkAccessManagerFactory; class QmlAbstractBinding; class QScriptDeclarativeClass; class QmlTypeNameScriptClass; @@ -99,8 +100,9 @@ class QmlTypeNameCache; class QmlComponentAttached; class QmlListScriptClass; class QmlCleanup; -class QmlBindingData; +class QmlDelayedError; class QmlWorkerScriptEngine; +class QmlGlobalScriptClass; class QmlScriptEngine : public QScriptEngine { @@ -160,13 +162,13 @@ public: QmlTypeNameScriptClass *typeNameClass; QmlListScriptClass *listClass; // Global script class - QScriptClass *globalClass; + QmlGlobalScriptClass *globalClass; // Registered cleanup handlers QmlCleanup *cleanup; // Bindings that have had errors during startup - QmlBindingData *erroredBindings; + QmlDelayedError *erroredBindings; int inProgressCreations; QmlScriptEngine scriptEngine; @@ -208,6 +210,8 @@ public: bool inBeginCreate; mutable QNetworkAccessManager *networkAccessManager; + mutable QmlNetworkAccessManagerFactory *networkAccessManagerFactory; + mutable bool accessManagerValid; QmlCompositeTypeManager typeManager; QStringList fileImportPath; @@ -307,16 +311,6 @@ public: }; -class QmlScriptClass : public QScriptClass -{ -public: - QmlScriptClass(QmlEngine *); - - static QVariant toVariant(QmlEngine *, const QScriptValue &); -protected: - QmlEngine *engine; -}; - QT_END_NAMESPACE #endif // QMLENGINE_P_H diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index cd6f582..3e8d71a 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -56,6 +56,20 @@ Q_DECLARE_METATYPE(QList<QObject *>); QT_BEGIN_NAMESPACE +bool QmlDelayedError::addError(QmlEnginePrivate *e) +{ + if (!e || prevError) return false; + + if (e->inProgressCreations == 0) return false; // Not in construction + + prevError = &e->erroredBindings; + nextError = e->erroredBindings; + e->erroredBindings = this; + if (nextError) nextError->prevError = &nextError; + + return true; +} + QmlExpressionData::QmlExpressionData() : expressionFunctionValid(false), expressionRewritten(false), me(0), trackChange(true), isShared(false), line(-1), guardList(0), guardListLength(0) @@ -100,52 +114,46 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, data->line = lineNumber; quint32 *exprData = (quint32 *)expr; - Q_ASSERT(*exprData == BasicScriptEngineData || - *exprData == PreTransformedQtScriptData); - if (*exprData == BasicScriptEngineData) { - data->sse.load((const char *)(exprData + 1), rc); - } else { - QmlCompiledData *dd = (QmlCompiledData *)rc; + QmlCompiledData *dd = (QmlCompiledData *)rc; - data->expressionRewritten = true; - data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]); + data->expressionRewritten = true; + data->expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]); - int progIdx = *(exprData + 1); - bool isShared = progIdx & 0x80000000; - progIdx &= 0x7FFFFFFF; + int progIdx = *(exprData); + bool isShared = progIdx & 0x80000000; + progIdx &= 0x7FFFFFFF; - QmlEngine *engine = ctxt->engine(); - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QmlEngine *engine = ctxt->engine(); + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - if (isShared) { + if (isShared) { - if (!dd->cachedClosures.at(progIdx)) { - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - scriptContext->pushScope(ep->contextClass->newSharedContext()); - dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line)); - scriptEngine->popContext(); - } + if (!dd->cachedClosures.at(progIdx)) { + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); + scriptContext->pushScope(ep->contextClass->newSharedContext()); + dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line)); + scriptEngine->popContext(); + } - data->expressionFunction = *dd->cachedClosures.at(progIdx); - data->isShared = true; - data->expressionFunctionValid = true; + data->expressionFunction = *dd->cachedClosures.at(progIdx); + data->isShared = true; + data->expressionFunctionValid = true; - } else { + } else { #if !defined(Q_OS_SYMBIAN) //XXX Why doesn't this work? - if (!dd->cachedPrograms.at(progIdx)) { - dd->cachedPrograms[progIdx] = - new QScriptProgram(data->expression, data->url, data->line); - } + if (!dd->cachedPrograms.at(progIdx)) { + dd->cachedPrograms[progIdx] = + new QScriptProgram(data->expression, data->url, data->line); + } - data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx)); + data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx)); #else - data->expressionFunction = evalInObjectScope(ctxt, me, data->expression); + data->expressionFunction = evalInObjectScope(ctxt, me, data->expression); #endif - data->expressionFunctionValid = true; - } + data->expressionFunctionValid = true; } data->QmlAbstractExpression::setContext(ctxt); @@ -258,10 +266,7 @@ QmlContext *QmlExpression::context() const QString QmlExpression::expression() const { Q_D(const QmlExpression); - if (d->data->sse.isValid()) - return QString::fromUtf8(d->data->sse.expression()); - else - return d->data->expression; + return d->data->expression; } /*! @@ -285,19 +290,6 @@ void QmlExpression::setExpression(const QString &expression) d->data->expressionFunctionValid = false; d->data->expressionRewritten = false; d->data->expressionFunction = QScriptValue(); - - d->data->sse.clear(); -} - -QVariant QmlExpressionPrivate::evalSSE() -{ -#ifdef Q_ENABLE_PERFORMANCE_LOG - QmlPerfTimer<QmlPerf::BindValueSSE> perfsse; -#endif - - QVariant rv = data->sse.run(data->context(), data->me); - - return rv; } void QmlExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine, @@ -442,7 +434,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) return rv; } - if (!data->sse.isValid() && data->expression.isEmpty()) + if (data->expression.isEmpty()) return rv; #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -463,11 +455,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) QmlExpressionData *localData = data; localData->addref(); - if (data->sse.isValid()) { - rv = evalSSE(); - } else { - rv = evalQtScript(secondaryScope, isUndefined); - } + rv = evalQtScript(secondaryScope, isUndefined); ep->currentExpression = lastCurrentExpression; ep->captureProperties = lastCaptureProperties; @@ -641,9 +629,16 @@ void QmlExpressionPrivate::clearGuards() for (int ii = 0; ii < data->guardListLength; ++ii) { if (data->guardList[ii].data()) { +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(data->guardList[ii].data(), data->guardList[ii].notifyIndex, q, notifyIdx); +#else + // QTBUG-6781 + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); +#endif } } @@ -684,9 +679,16 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu } } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { // Cache miss +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(data->guardList[ii].data(), data->guardList[ii].notifyIndex, q, notifyIdx); +#else + // QTBUG-6781 + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); +#endif } /* else { // Cache miss, but nothing to do @@ -732,9 +734,16 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu for (int ii = properties.count(); ii < data->guardListLength; ++ii) { if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(data->guardList[ii].data(), data->guardList[ii].notifyIndex, q, notifyIdx); +#else + // QTBUG-6781 + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); +#endif } } diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index cc02d56..4df7641 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -58,7 +58,6 @@ class QmlRefCount; class QmlEngine; class QmlContext; class QmlExpressionPrivate; -class QmlBasicScript; class Q_DECLARATIVE_EXPORT QmlExpression : public QObject { Q_OBJECT diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 8561a57..1fbb075 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -55,7 +55,6 @@ #include "qmlexpression.h" -#include "qmlbasicscript_p.h" #include "qmlengine_p.h" #include "qmlguard_p.h" @@ -84,7 +83,30 @@ private: QmlAbstractExpression *m_nextExpression; }; -class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount +class QmlDelayedError +{ +public: + inline QmlDelayedError() : nextError(0), prevError(0) {} + inline ~QmlDelayedError() { removeError(); } + + QmlError error; + + bool addError(QmlEnginePrivate *); + + inline void removeError() { + if (!prevError) return; + if (nextError) nextError->prevError = prevError; + *prevError = nextError; + nextError = 0; + prevError = 0; + } + +private: + QmlDelayedError *nextError; + QmlDelayedError **prevError; +}; + +class QmlExpressionData : public QmlAbstractExpression, public QmlDelayedError, public QmlRefCount { public: QmlExpressionData(); @@ -97,9 +119,6 @@ public: bool expressionRewritten:1; QScriptValue expressionFunction; - QmlError error; - - QmlBasicScript sse; QObject *me; bool trackChange; @@ -139,18 +158,12 @@ public: QmlExpressionPrivate(QmlExpressionData *); ~QmlExpressionPrivate(); - enum CompiledDataType { - BasicScriptEngineData = 1, - PreTransformedQtScriptData = 2 - }; - void init(QmlContext *, const QString &, QObject *); void init(QmlContext *, void *, QmlRefCount *, QObject *, const QString &, int); QmlExpressionData *data; QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); - QVariant evalSSE(); QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0); void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties); diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp index 5387e03..13c1017 100644 --- a/src/declarative/qml/qmlglobalscriptclass.cpp +++ b/src/declarative/qml/qmlglobalscriptclass.cpp @@ -101,5 +101,21 @@ void QmlGlobalScriptClass::setProperty(QScriptValue &object, engine()->currentContext()->throwError(error); } +void QmlGlobalScriptClass::explicitSetProperty(const QString &name, const QScriptValue &value) +{ + QScriptValue v = engine()->newObject(); + globalObject = engine()->globalObject(); + + QScriptValueIterator iter(globalObject); + while (iter.hasNext()) { + iter.next(); + v.setProperty(iter.scriptName(), iter.value()); + } + + v.setProperty(name, value); + v.setScriptClass(this); + engine()->setGlobalObject(v); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlglobalscriptclass_p.h b/src/declarative/qml/qmlglobalscriptclass_p.h index 1658c27..56c91fe 100644 --- a/src/declarative/qml/qmlglobalscriptclass_p.h +++ b/src/declarative/qml/qmlglobalscriptclass_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE -class QmlGlobalScriptClass : public QScriptClass +class Q_AUTOTEST_EXPORT QmlGlobalScriptClass : public QScriptClass { public: QmlGlobalScriptClass(QScriptEngine *); @@ -72,6 +72,8 @@ public: virtual void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + void explicitSetProperty(const QString &, const QScriptValue &); + private: QScriptValue globalObject; }; diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 2ddad49..d99bf65 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -161,9 +161,6 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreCompiledBinding: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; - case QmlInstruction::StoreIdOptBinding: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_ID_OPT_BINDING\t" << instr->assignIdOptBinding.property << "\t" << instr->assignIdOptBinding.id; - break; case QmlInstruction::StoreValueSource: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 44fa196..0639397 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -129,7 +129,6 @@ public: StoreBinding, /* assignBinding */ StoreCompiledBinding, /* assignBinding */ - StoreIdOptBinding, /* assignIdOptBinding */ StoreValueSource, /* assignValueSource */ StoreValueInterceptor, /* assignValueInterceptor */ diff --git a/src/declarative/qml/qmllistscriptclass.cpp b/src/declarative/qml/qmllistscriptclass.cpp index b275625..d4cdc6e 100644 --- a/src/declarative/qml/qmllistscriptclass.cpp +++ b/src/declarative/qml/qmllistscriptclass.cpp @@ -49,11 +49,12 @@ QT_BEGIN_NAMESPACE struct ListData : public QScriptDeclarativeClass::Object { QmlGuard<QObject> object; int propertyIdx; - QmlListScriptClass::ListType type; + QmlListScriptClass::ListCategory type; + int propertyType; }; QmlListScriptClass::QmlListScriptClass(QmlEngine *e) -: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(e)), engine(e) +: QmlScriptClass(QmlEnginePrivate::getScriptEngine(e)), engine(e) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); Q_UNUSED(scriptEngine); @@ -65,7 +66,7 @@ QmlListScriptClass::~QmlListScriptClass() { } -QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListType type) +QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListCategory type, int propType) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); @@ -76,6 +77,7 @@ QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListType t data->object = object; data->propertyIdx = propId; data->type = type; + data->propertyType = propType; return newObject(scriptEngine, this, data); } @@ -100,14 +102,14 @@ QmlListScriptClass::queryProperty(Object *object, const Identifier &name, } } -QmlListScriptClass::Value QmlListScriptClass::property(Object *obj, const Identifier &name) +QmlListScriptClass::ScriptValue QmlListScriptClass::property(Object *obj, const Identifier &name) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); ListData *data = (ListData *)obj; if (!data->object) - return scriptEngine->undefinedValue(); + return Value(); void *list = 0; void *args[] = { &list, 0 }; @@ -115,7 +117,7 @@ QmlListScriptClass::Value QmlListScriptClass::property(Object *obj, const Identi data->propertyIdx, args); if (!list) - return scriptEngine->undefinedValue(); + return Value(); if (data->type == QListPtr) { const QList<QObject *> &qlist = *((QList<QObject *>*)list); @@ -125,9 +127,9 @@ QmlListScriptClass::Value QmlListScriptClass::property(Object *obj, const Identi if (name == m_lengthId.identifier) return Value(scriptEngine, count); else if (lastIndex < count) - return enginePriv->objectClass->newQObject(qlist.at(lastIndex)); + return Value(scriptEngine, enginePriv->objectClass->newQObject(qlist.at(lastIndex))); else - return scriptEngine->undefinedValue(); + return Value(); } else { Q_ASSERT(data->type == QmlListPtr); @@ -138,11 +140,34 @@ QmlListScriptClass::Value QmlListScriptClass::property(Object *obj, const Identi if (name == m_lengthId.identifier) return Value(scriptEngine, count); else if (lastIndex < count) - return enginePriv->objectClass->newQObject(qmllist.at(lastIndex)); + return Value(scriptEngine, enginePriv->objectClass->newQObject(qmllist.at(lastIndex))); else - return scriptEngine->undefinedValue(); + return Value(); } } +QVariant QmlListScriptClass::toVariant(Object *obj, bool *ok) +{ + ListData *data = (ListData *)obj; + + if (!data->object) { + if (ok) *ok = false; + return QVariant(); + } + + void *list = 0; + void *args[] = { &list, 0 }; + QMetaObject::metacall(data->object, QMetaObject::ReadProperty, + data->propertyIdx, args); + + if (!list) { + if (ok) *ok = false; + return QVariant(); + } + + if (ok) *ok = true; + return QVariant(data->propertyType, &list); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmllistscriptclass_p.h b/src/declarative/qml/qmllistscriptclass_p.h index 43ca929..e484b34 100644 --- a/src/declarative/qml/qmllistscriptclass_p.h +++ b/src/declarative/qml/qmllistscriptclass_p.h @@ -53,24 +53,25 @@ // We mean it. // -#include <private/qscriptdeclarativeclass_p.h> +#include <private/qmlscriptclass_p.h> QT_BEGIN_NAMESPACE class QmlEngine; -class QmlListScriptClass : public QScriptDeclarativeClass +class QmlListScriptClass : public QmlScriptClass { public: QmlListScriptClass(QmlEngine *); ~QmlListScriptClass(); - enum ListType { QListPtr, QmlListPtr }; - QScriptValue newList(QObject *, int, ListType); + enum ListCategory { QListPtr, QmlListPtr }; + QScriptValue newList(QObject *, int, ListCategory, int); protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual Value property(Object *, const Identifier &); + virtual ScriptValue property(Object *, const Identifier &); + virtual QVariant toVariant(Object *, bool *ok); private: PersistentIdentifier m_lengthId; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 6738370..0603a9c 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -46,10 +46,12 @@ #include "qml.h" #include "qmlbinding.h" #include "qmlcontext.h" +#include "qmlcontext_p.h" #include "qmlboundsignal_p.h" #include "qmlengine.h" #include "qmlengine_p.h" #include "qmldeclarativedata_p.h" +#include "qmlstringconverters_p.h" #include <qfxperf_p_p.h> @@ -160,17 +162,13 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (enginePrivate && name.at(0).isUpper()) { // Attached property - //### needs to be done in a better way - QmlCompositeTypeData *typeData = - enginePrivate->typeManager.get(context->baseUrl()); - - if (typeData) { - QmlType *t = 0; - enginePrivate->resolveType(typeData->imports, name.toUtf8(), &t, 0, 0, 0, 0); - if (t && t->attachedPropertiesFunction()) { - attachedFunc = t->index(); + // ### What about qualified types? + QmlTypeNameCache *tnCache = QmlContextPrivate::get(context)->imports; + if (tnCache) { + QmlTypeNameCache::Data *d = tnCache->data(name); + if (d && d->type && d->type->attachedPropertiesFunction()) { + attachedFunc = d->type->index(); } - typeData->release(); } return; @@ -438,6 +436,17 @@ bool QmlMetaProperty::isDesignable() const } /*! + Returns true if the property is resettable, otherwise false. +*/ +bool QmlMetaProperty::isResettable() const +{ + if (type() & Property && d->core.isValid() && d->object) + return d->core.flags & QmlPropertyCache::Data::IsResettable; + else + return false; +} + +/*! Returns true if the QmlMetaProperty refers to a valid property, otherwise false. */ @@ -676,7 +685,7 @@ QVariant QmlMetaProperty::read() const return QVariant(); - } else if (type() & Property) { + } else if (type() & Property || type() & Attached) { return d->readValueProperty(); @@ -954,6 +963,14 @@ bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } + } else if (vt == QVariant::String) { + bool ok = false; + QVariant v = QmlStringConverters::variantFromString(value.toString(), t, &ok); + if (!ok) + return false; + + void *a[] = { (void *)v.constData(), 0, &status, &flags}; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else { return false; } @@ -970,6 +987,20 @@ bool QmlMetaProperty::write(const QVariant &value) const return write(value, 0); } +/*! + Resets the property value. +*/ +bool QmlMetaProperty::reset() const +{ + if (isResettable()) { + void *args[] = { 0 }; + QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex, args); + return true; + } else { + return false; + } +} + bool QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const { if (d->object && type() & Property && d->core.isValid() && isWritable()) @@ -1122,24 +1153,51 @@ QmlMetaPropertyPrivate::restore(const QByteArray &data, QObject *object, QmlCont Creates a QmlMetaProperty for the property \a name of \a obj. Unlike the QmlMetaProperty(QObject*, QString, QmlContext*) constructor, this static function - will correctly handle dot properties. + will correctly handle dot properties, including value types and attached properties. */ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, const QString &name, QmlContext *context) { - QStringList path = name.split(QLatin1Char('.')); + QmlTypeNameCache *typeNameCache = context?QmlContextPrivate::get(context)->imports:0; + QStringList path = name.split(QLatin1Char('.')); QObject *object = obj; for (int jj = 0; jj < path.count() - 1; ++jj) { const QString &pathName = path.at(jj); + + if (QmlTypeNameCache::Data *data = typeNameCache?typeNameCache->data(pathName):0) { + if (data->type) { + QmlAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); + if (!func) + return QmlMetaProperty(); + object = qmlAttachedPropertiesObjectById(data->type->index(), object); + if (!object) + return QmlMetaProperty(); + continue; + } else { + Q_ASSERT(data->typeNamespace); + ++jj; + data = data->typeNamespace->data(path.at(jj)); + if (!data || !data->type) + return QmlMetaProperty(); + QmlAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); + if (!func) + return QmlMetaProperty(); + object = qmlAttachedPropertiesObjectById(data->type->index(), object); + if (!object) + return QmlMetaProperty(); + continue; + } + } + QmlMetaProperty prop(object, pathName, context); - if (jj == path.count() - 2 && - prop.propertyType() < (int)QVariant::UserType && + if (jj == path.count() - 2 && prop.propertyType() < (int)QVariant::UserType && qmlValueTypes()->valueTypes[prop.propertyType()]) { - // We're now at a value type property + // We're now at a value type property. We can use a global valuetypes array as we + // never actually use the objects, just look up their properties. QObject *typeObject = qmlValueTypes()->valueTypes[prop.propertyType()]; int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index dcb5905..240f5a2 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -88,6 +88,7 @@ public: enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 }; Q_DECLARE_FLAGS(WriteFlags, WriteFlag) bool write(const QVariant &, QmlMetaProperty::WriteFlags) const; + bool reset() const; bool hasChangedNotifier() const; bool needsChangedNotifier() const; @@ -108,6 +109,7 @@ public: bool isDefault() const; bool isWritable() const; bool isDesignable() const; + bool isResettable() const; bool isValid() const; QObject *object() const; diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp new file mode 100644 index 0000000..6ae20de --- /dev/null +++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 "qmlnetworkaccessmanagerfactory.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QmlNetworkAccessManagerFactory + \brief The QmlNetworkAccessManagerFactory class provides a factory for QNetworkAccessManager + + QNetworkAccessManager is used for all network access by QML. + By implementing a factory it is possible to create custom + QNetworkAccessManager with specialized caching, proxy and + cookie support. + + To implement a factory, subclass QmlNetworkAccessManagerFactory and implement + the create() method. + + If the created QNetworkAccessManager becomes invalid, due to a + change in proxy settings, for example, call the invalidate() method. + This will cause all QNetworkAccessManagers to be recreated. + + Note: the create() method may be called by multiple threads, so ensure the + implementation of this method is reentrant. +*/ +QmlNetworkAccessManagerFactory::~QmlNetworkAccessManagerFactory() +{ +} + +/*! + \fn QNetworkAccessManager *QmlNetworkAccessManagerFactory::create(QObject *parent) + + Implement this method to create a QNetworkAccessManager with \a parent. + This allows proxies, caching and cookie support to be setup appropriately. + + Note: this method may be called by multiple threads, so ensure the + implementation of this method is reentrant. +*/ + +/*! + Invalidates all currently created QNetworkAccessManager(s) which + will cause create() to be called for subsequent network access. +*/ +void QmlNetworkAccessManagerFactory::invalidate() +{ + emit invalidated(); +} + +/*! + \internal + \fn QmlNetworkAccessManagerFactory::invalidated() +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h new file mode 100644 index 0000000..f64918b --- /dev/null +++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 QMLNETWORKACCESSMANAGERFACTORY_H +#define QMLNETWORKACCESSMANAGERFACTORY_H + +#include <QtCore/qobject.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QNetworkAccessManager; +class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory : public QObject +{ + Q_OBJECT +public: + virtual ~QmlNetworkAccessManagerFactory(); + void invalidate(); + virtual QNetworkAccessManager *create(QObject *parent) = 0; + +Q_SIGNALS: + void invalidated(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLNETWORKACCESSMANAGERFACTORY_H diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index fbd123a..5fd76c6 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -51,6 +51,9 @@ #include "qmlvmemetaobject_p.h" #include <QtCore/qtimer.h> +#include <QtCore/qvarlengtharray.h> + +Q_DECLARE_METATYPE(QScriptValue); QT_BEGIN_NAMESPACE @@ -66,8 +69,11 @@ struct ObjectData : public QScriptDeclarativeClass::Object { QtScript for QML. */ QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) -: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0), - engine(bindEngine) +: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + methods(bindEngine), +#endif + lastData(0), engine(bindEngine) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); @@ -159,23 +165,25 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, if (lastData) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; - if (!evalContext && context()) { - // Global object, QScriptContext activation object, QmlContext object - QScriptValue scopeNode = scopeChainValue(context(), -3); - Q_ASSERT(scopeNode.isValid()); - Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass); + if (!(hints & SkipAttachedProperties)) { + if (!evalContext && context()) { + // Global object, QScriptContext activation object, QmlContext object + QScriptValue scopeNode = scopeChainValue(context(), -3); + Q_ASSERT(scopeNode.isValid()); + Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass); - evalContext = enginePrivate->contextClass->contextFromValue(scopeNode); - } + evalContext = enginePrivate->contextClass->contextFromValue(scopeNode); + } - if (evalContext) { - QmlContextPrivate *cp = QmlContextPrivate::get(evalContext); + if (evalContext) { + QmlContextPrivate *cp = QmlContextPrivate::get(evalContext); - if (cp->imports) { - QmlTypeNameCache::Data *data = cp->imports->data(name); - if (data) { - lastTNData = data; - return QScriptClass::HandlesReadAccess; + if (cp->imports) { + QmlTypeNameCache::Data *data = cp->imports->data(name); + if (data) { + lastTNData = data; + return QScriptClass::HandlesReadAccess; + } } } } @@ -189,42 +197,49 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return 0; } -QmlObjectScriptClass::Value +QmlObjectScriptClass::ScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name) { return property(toQObject(object), name); } -QmlObjectScriptClass::Value +QmlObjectScriptClass::ScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name) { + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + if (name == m_destroyId.identifier) - return m_destroy; + return Value(scriptEngine, m_destroy); else if (name == m_toStringId.identifier) - return m_toString; + return Value(scriptEngine, m_toString); if (lastData && !lastData->isValid()) - return QmlEnginePrivate::getScriptEngine(engine)->undefinedValue(); + return Value(); Q_ASSERT(obj); - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); if (lastTNData) { if (lastTNData->type) - return enginePriv->typeNameClass->newObject(obj, lastTNData->type); + return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type)); else - return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace); + return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace)); } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) { if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) { - return ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex); + return Value(scriptEngine, ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex)); } else { - // ### Optimize +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + // Uncomment to use QtScript method call logic + // QScriptValue sobj = scriptEngine->newQObject(obj); + // return Value(scriptEngine, sobj.property(toString(name))); + return Value(scriptEngine, methods.newMethod(obj, lastData)); +#else QScriptValue sobj = scriptEngine->newQObject(obj); - return sobj.property(toString(name)); + return Value(scriptEngine, sobj.property(toString(name))); +#endif } } else { if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) { @@ -235,25 +250,23 @@ QmlObjectScriptClass::property(QObject *obj, const Identifier &name) if ((uint)lastData->propType < QVariant::UserType) { QmlValueType *valueType = enginePriv->valueTypes[lastData->propType]; if (valueType) - return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); + return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType)); } if (lastData->flags & QmlPropertyCache::Data::IsQList) { - return enginePriv->listClass->newList(obj, lastData->coreIndex, - QmlListScriptClass::QListPtr); + return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QListPtr, lastData->propType)); } else if (lastData->flags & QmlPropertyCache::Data::IsQmlList) { - return enginePriv->listClass->newList(obj, lastData->coreIndex, - QmlListScriptClass::QmlListPtr); + return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QmlListPtr, lastData->propType)); } else if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { QObject *rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return newQObject(rv, lastData->propType); + return Value(scriptEngine, newQObject(rv, lastData->propType)); } else if (lastData->flags & QmlPropertyCache::Data::IsQScriptValue) { QScriptValue rv = scriptEngine->nullValue(); void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return rv; + return Value(scriptEngine, rv); } else if (lastData->propType == QMetaType::QReal) { qreal rv = 0; void *args[] = { &rv, 0 }; @@ -291,7 +304,7 @@ QmlObjectScriptClass::property(QObject *obj, const Identifier &name) return Value(scriptEngine, rv); } else { QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); - return enginePriv->scriptValueFromVariant(var); + return Value(scriptEngine, enginePriv->scriptValueFromVariant(var)); } } @@ -341,12 +354,18 @@ void QmlObjectScriptClass::setProperty(QObject *obj, evalContext = enginePriv->contextClass->contextFromValue(scopeNode); } - // ### Can well known types be optimized? - QVariant v = QmlScriptClass::toVariant(engine, value); QmlAbstractBinding *delBinding = QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0); if (delBinding) delBinding->destroy(); - QmlMetaPropertyPrivate::write(obj, *lastData, v, evalContext); + + if (value.isUndefined() && lastData->flags & QmlPropertyCache::Data::IsResettable) { + void *a[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a); + } else { + // ### Can well known types be optimized? + QVariant v = QmlScriptClass::toVariant(engine, value); + QmlMetaPropertyPrivate::write(obj, *lastData, v, evalContext); + } } bool QmlObjectScriptClass::isQObject() const @@ -425,5 +444,246 @@ QStringList QmlObjectScriptClass::propertyNames(Object *object) return cache->propertyNames(); } +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + +struct MethodData : public QScriptDeclarativeClass::Object { + MethodData(QObject *o, const QmlPropertyCache::Data &d) : object(o), data(d) {} + + QmlGuard<QObject> object; + QmlPropertyCache::Data data; +}; + +QmlObjectMethodScriptClass::QmlObjectMethodScriptClass(QmlEngine *bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), + engine(bindEngine) +{ + setSupportsCall(true); +} + +QmlObjectMethodScriptClass::~QmlObjectMethodScriptClass() +{ +} + +QScriptValue QmlObjectMethodScriptClass::newMethod(QObject *object, const QmlPropertyCache::Data *method) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return newObject(scriptEngine, this, new MethodData(object, *method)); +} + +namespace { +struct MetaCallArgument { + inline MetaCallArgument(); + inline ~MetaCallArgument(); + inline void *dataPtr(); + + inline void initAsType(int type, QmlEngine *); + void fromScriptValue(int type, QmlEngine *, const QScriptValue &); + inline QScriptDeclarativeClass::Value toValue(QmlEngine *); + +private: + MetaCallArgument(const MetaCallArgument &); + + inline void cleanup(); + + char *data[16]; + int type; +}; +} + +MetaCallArgument::MetaCallArgument() +: type(QVariant::Invalid) +{ +} + +MetaCallArgument::~MetaCallArgument() +{ + cleanup(); +} + +void MetaCallArgument::cleanup() +{ + if (type == QMetaType::QString) { + ((QString *)data)->~QString(); + } else if (type == -1 || type == qMetaTypeId<QVariant>()) { + ((QVariant *)data)->~QVariant(); + } else if (type == qMetaTypeId<QScriptValue>()) { + ((QScriptValue *)data)->~QScriptValue(); + } +} + +void *MetaCallArgument::dataPtr() +{ + if (type == -1) + return ((QVariant *)data)->data(); + else + return (void *)data; +} + +void MetaCallArgument::initAsType(int callType, QmlEngine *e) +{ + if (type != 0) { cleanup(); type = 0; } + if (callType == 0) return; + + QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e); + + if (callType == qMetaTypeId<QScriptValue>()) { + new (data) QScriptValue(engine->undefinedValue()); + type = callType; + } else if (callType == QMetaType::Int || + callType == QMetaType::UInt || + callType == QMetaType::Bool || + callType == QMetaType::Double || + callType == QMetaType::Float) { + type = callType; + } else if (callType == QMetaType::QObjectStar) { + *((QObject **)data) = 0; + type = callType; + } else if (callType == QMetaType::QString) { + new (data) QString(); + type = callType; + } else if (callType == qMetaTypeId<QVariant>()) { + type = qMetaTypeId<QVariant>(); + new (data) QVariant(); + } else { + type = -1; + new (data) QVariant(callType, (void *)0); + } +} + +void MetaCallArgument::fromScriptValue(int callType, QmlEngine *engine, const QScriptValue &value) +{ + if (type != 0) { cleanup(); type = 0; } + + if (callType == qMetaTypeId<QScriptValue>()) { + new (data) QScriptValue(value); + type = qMetaTypeId<QScriptValue>(); + } else if (callType == QMetaType::Int) { + *((int *)data) = int(value.toInt32()); + type = callType; + } else if (callType == QMetaType::UInt) { + *((uint *)data) = uint(value.toUInt32()); + type = callType; + } else if (callType == QMetaType::Bool) { + *((bool *)data) = value.toBool(); + type = callType; + } else if (callType == QMetaType::Double) { + *((double *)data) = double(value.toNumber()); + type = callType; + } else if (callType == QMetaType::Float) { + *((float *)data) = float(value.toNumber()); + type = callType; + } else if (callType == QMetaType::QString) { + if (value.isNull() || value.isUndefined()) + new (data) QString(); + else + new (data) QString(value.toString()); + type = callType; + } else if (callType == QMetaType::QObjectStar) { + *((QObject **)data) = value.toQObject(); + type = callType; + } else if (callType == qMetaTypeId<QVariant>()) { + new (data) QVariant(QmlScriptClass::toVariant(engine, value)); + type = callType; + } else { + new (data) QVariant(); + type = -1; + + QVariant v = QmlScriptClass::toVariant(engine, value); + if (v.userType() == callType) { + *((QVariant *)data) = v; + } else if (v.canConvert((QVariant::Type)callType)) { + *((QVariant *)data) = v; + ((QVariant *)data)->convert((QVariant::Type)callType); + } else { + *((QVariant *)data) = QVariant(callType, (void *)0); + } + } +} + +QScriptDeclarativeClass::Value MetaCallArgument::toValue(QmlEngine *e) +{ + QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e); + + if (type == qMetaTypeId<QScriptValue>()) { + return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)data)); + } else if (type == QMetaType::Int) { + return QScriptDeclarativeClass::Value(engine, *((int *)data)); + } else if (type == QMetaType::UInt) { + return QScriptDeclarativeClass::Value(engine, *((uint *)data)); + } else if (type == QMetaType::Bool) { + return QScriptDeclarativeClass::Value(engine, *((bool *)data)); + } else if (type == QMetaType::Double) { + return QScriptDeclarativeClass::Value(engine, *((double *)data)); + } else if (type == QMetaType::Float) { + return QScriptDeclarativeClass::Value(engine, *((float *)data)); + } else if (type == QMetaType::QString) { + return QScriptDeclarativeClass::Value(engine, *((QString *)data)); + } else if (type == QMetaType::QObjectStar) { + return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->objectClass->newQObject(*((QObject **)data))); + } else if (type == -1 || type == qMetaTypeId<QVariant>()) { + return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->scriptValueFromVariant(*((QVariant *)data))); + } else { + return QScriptDeclarativeClass::Value(); + } +} + +QmlObjectMethodScriptClass::Value QmlObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt) +{ + MethodData *method = static_cast<MethodData *>(o); + + if (method->data.flags & QmlPropertyCache::Data::HasArguments) { + + QMetaMethod m = method->object->metaObject()->method(method->data.coreIndex); + QList<QByteArray> argTypeNames = m.parameterTypes(); + QVarLengthArray<int, 9> argTypes(argTypeNames.count()); + + // ### Cache + for (int ii = 0; ii < argTypeNames.count(); ++ii) { + argTypes[ii] = QMetaType::type(argTypeNames.at(ii)); + if (argTypes[ii] == QVariant::Invalid) + return Value(ctxt, ctxt->throwError(QString(QLatin1String("Unknown method parameter type: %1")).arg(QLatin1String(argTypeNames.at(ii))))); + } + + if (argTypes.count() > ctxt->argumentCount()) + return Value(ctxt, ctxt->throwError("Insufficient arguments")); + + QVarLengthArray<MetaCallArgument, 9> args(argTypes.count() + 1); + args[0].initAsType(method->data.propType, engine); + + for (int ii = 0; ii < argTypes.count(); ++ii) + args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii)); + + QVarLengthArray<void *, 9> argData(args.count()); + for (int ii = 0; ii < args.count(); ++ii) + argData[ii] = args[ii].dataPtr(); + + QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, argData.data()); + + return args[0].toValue(engine); + + } else if (method->data.propType != 0) { + + MetaCallArgument arg; + arg.initAsType(method->data.propType, engine); + + void *args[] = { arg.dataPtr() }; + + QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args); + + return arg.toValue(engine); + + } else { + + void *args[] = { 0 }; + QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args); + return Value(); + + } + return Value(); +} + +#endif + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index 457eb2b..ebb2c2a 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -56,9 +56,7 @@ #include "qmlpropertycache_p.h" #include "qmltypenamecache_p.h" -#include <QtScript/qscriptclass.h> - -#include <private/qscriptdeclarativeclass_p.h> +#include <private/qmlscriptclass_p.h> QT_BEGIN_NAMESPACE @@ -66,7 +64,24 @@ class QmlEngine; class QScriptContext; class QScriptEngine; class QmlContext; -class Q_AUTOTEST_EXPORT QmlObjectScriptClass : public QScriptDeclarativeClass + +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) +class Q_AUTOTEST_EXPORT QmlObjectMethodScriptClass : public QScriptDeclarativeClass +{ +public: + QmlObjectMethodScriptClass(QmlEngine *); + ~QmlObjectMethodScriptClass(); + + QScriptValue newMethod(QObject *, const QmlPropertyCache::Data *); +protected: + virtual Value call(Object *, QScriptContext *); + +private: + QmlEngine *engine; +}; +#endif + +class Q_AUTOTEST_EXPORT QmlObjectScriptClass : public QmlScriptClass { public: QmlObjectScriptClass(QmlEngine *); @@ -86,7 +101,9 @@ public: QScriptClass::QueryFlags flags, QmlContext *evalContext, QueryHints hints = 0); - Value property(QObject *, const Identifier &); + + ScriptValue property(QObject *, const Identifier &); + void setProperty(QObject *, const Identifier &name, const QScriptValue &, QmlContext *evalContext = 0); virtual QStringList propertyNames(Object *); @@ -95,12 +112,16 @@ protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual Value property(Object *, const Identifier &); + virtual ScriptValue property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); virtual bool isQObject() const; virtual QObject *toQObject(Object *, bool *ok = 0); private: +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + QmlObjectMethodScriptClass methods; +#endif + QmlTypeNameCache::Data *lastTNData; QmlPropertyCache::Data *lastData; QmlPropertyCache::Data local; @@ -115,6 +136,7 @@ private: QmlEngine *engine; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlObjectScriptClass::QueryHints); QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 3bbf1fe..51753b8 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -61,6 +61,8 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p, QmlEngine *engine) flags |= Data::IsConstant; if (p.isWritable()) flags |= Data::IsWritable; + if (p.isResettable()) + flags |= Data::IsResettable; if (propType == qMetaTypeId<QmlBinding *>()) { flags |= Data::IsQmlBinding; @@ -84,6 +86,15 @@ void QmlPropertyCache::Data::load(const QMetaMethod &m) { coreIndex = m.methodIndex(); flags |= Data::IsFunction; + propType = QVariant::Invalid; + + const char *returnType = m.typeName(); + if (returnType) + propType = QMetaType::type(returnType); + + QList<QByteArray> params = m.parameterTypes(); + if (!params.isEmpty()) + flags |= Data::HasArguments; } diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index a94b2a1..8d54e35 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -80,16 +80,21 @@ public: // Can apply to all properties, except IsFunction IsConstant = 0x00000001, IsWritable = 0x00000002, + IsResettable = 0x00000004, - // These are mutually exclusive - IsFunction = 0x00000004, - IsVMEFunction = 0x00000008, + // These are mutualy exclusive + IsFunction = 0x00000008, IsQObjectDerived = 0x00000010, IsEnumType = 0x00000020, IsQmlList = 0x00000040, IsQList = 0x00000080, IsQmlBinding = 0x00000100, - IsQScriptValue = 0x00000200 + IsQScriptValue = 0x00000200, + + // Apply only to IsFunctions + IsVMEFunction = 0x00000400, + HasArguments = 0x00000800 + }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/declarative/qml/qmlbindingvme_p.h b/src/declarative/qml/qmlscriptclass_p.h index 4ef7d04..7ffb2ae 100644 --- a/src/declarative/qml/qmlbindingvme_p.h +++ b/src/declarative/qml/qmlscriptclass_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QMLBINDINGVME_P_H -#define QMLBINDINGVME_P_H +#ifndef QMLSCRIPTCLASS_P_H +#define QMLSCRIPTCLASS_P_H // // W A R N I N G @@ -53,65 +53,37 @@ // We mean it. // -#include <QtCore/qglobal.h> -#include <private/qmlbasicscript_p.h> +#include <QtScript/qscriptclass.h> #include <private/qscriptdeclarativeclass_p.h> -#include "qmlguard_p.h" - -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QObject; -class QmlContextPrivate; -class QmlBindingVME +class QmlEngine; +class QmlScriptClass : public QScriptDeclarativeClass { public: - struct Config { - Config() : target(0), targetSlot(-1), subscriptions(0), identifiers(0) {} - ~Config() { delete [] subscriptions; delete [] identifiers; } - QObject *target; - int targetSlot; - - struct Subscription { - QmlGuard<QObject> source; - int notifyIndex; - }; - Subscription *subscriptions; - QScriptDeclarativeClass::PersistentIdentifier *identifiers; + QmlScriptClass(QScriptEngine *); + + static QVariant toVariant(QmlEngine *, const QScriptValue &); + +#if (QT_VERSION < QT_VERSION_CHECK(4, 6, 2)) + struct Value : public QScriptValue { + Value() : QScriptValue() {} + Value(QScriptEngine *engine, int v) : QScriptValue(engine, v) {} + Value(QScriptEngine *engine, uint v) : QScriptValue(engine, v) {} + Value(QScriptEngine *engine, bool v) : QScriptValue(engine, v) {} + Value(QScriptEngine *engine, double v) : QScriptValue(engine, v) {} + Value(QScriptEngine *engine, float v) : QScriptValue(engine, v) {} + Value(QScriptEngine *engine, const QString &v) : QScriptValue(engine, v) {} + Value(QScriptEngine *, const QScriptValue &v) : QScriptValue(v) {} }; - static void init(const char *program, Config *config, - quint32 **sigTable, quint32 *bindingCount); - static void run(const char *program, int instr, - Config *config, QmlContextPrivate *context, - QObject **scopes, QObject **outputs); - static void dump(const char *); -}; - -class QmlBindingCompilerPrivate; -class QmlBindingCompiler -{ -public: - QmlBindingCompiler(); - ~QmlBindingCompiler(); - - // Returns true if bindings were compiled - bool isValid() const; - - // -1 on failure, otherwise the binding index to use - int compile(const QmlBasicScript::Expression &, QmlEnginePrivate *); - - // Returns the compiled program - QByteArray program() const; - -private: - QmlBindingCompilerPrivate *d; + typedef QScriptValue ScriptValue; +#else + typedef Value ScriptValue; +#endif }; QT_END_NAMESPACE -QT_END_HEADER - -#endif // QMLBINDINGVME_P_H - +#endif // QMLSCRIPTCLASS_P_H diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp index c68654f..2963ab5 100644 --- a/src/declarative/qml/qmlstringconverters.cpp +++ b/src/declarative/qml/qmlstringconverters.cpp @@ -47,6 +47,7 @@ #include <QtCore/qrect.h> #include <QtCore/qsize.h> #include <QtCore/qvariant.h> +#include <QtCore/qdatetime.h> QT_BEGIN_NAMESPACE @@ -94,14 +95,43 @@ QVariant QmlStringConverters::variantFromString(const QString &s) if (ok) return QVariant(p); QSizeF sz = sizeFFromString(s, &ok); if (ok) return QVariant(sz); - bool b = boolFromString(s, &ok); - if (ok) return QVariant(b); QVector3D v = vector3DFromString(s, &ok); if (ok) return qVariantFromValue(v); return QVariant(s); } +QVariant QmlStringConverters::variantFromString(const QString &s, int preferredType, bool *ok) +{ + switch (preferredType) { + case QMetaType::QColor: + return QVariant::fromValue(colorFromString(s, ok)); + case QMetaType::QDate: + return QVariant::fromValue(dateFromString(s, ok)); + case QMetaType::QTime: + return QVariant::fromValue(timeFromString(s, ok)); + case QMetaType::QDateTime: + return QVariant::fromValue(dateTimeFromString(s, ok)); + case QMetaType::QPointF: + return QVariant::fromValue(pointFFromString(s, ok)); + case QMetaType::QPoint: + return QVariant::fromValue(pointFFromString(s, ok).toPoint()); + case QMetaType::QSizeF: + return QVariant::fromValue(sizeFFromString(s, ok)); + case QMetaType::QSize: + return QVariant::fromValue(sizeFFromString(s, ok).toSize()); + case QMetaType::QRectF: + return QVariant::fromValue(rectFFromString(s, ok)); + case QMetaType::QRect: + return QVariant::fromValue(rectFFromString(s, ok).toRect()); + case QMetaType::QVector3D: + return QVariant::fromValue(vector3DFromString(s, ok)); + default: + if (ok) *ok = false; + return QVariant(); + } +} + QColor QmlStringConverters::colorFromString(const QString &s, bool *ok) { if (s.startsWith(QLatin1Char('#')) && s.length() == 9) { @@ -120,6 +150,27 @@ QColor QmlStringConverters::colorFromString(const QString &s, bool *ok) } } +QDate QmlStringConverters::dateFromString(const QString &s, bool *ok) +{ + QDate d = QDate::fromString(s, Qt::ISODate); + if (ok) *ok = d.isValid(); + return d; +} + +QTime QmlStringConverters::timeFromString(const QString &s, bool *ok) +{ + QTime t = QTime::fromString(s, Qt::ISODate); + if (ok) *ok = t.isValid(); + return t; +} + +QDateTime QmlStringConverters::dateTimeFromString(const QString &s, bool *ok) +{ + QDateTime d = QDateTime::fromString(s, Qt::ISODate); + if (ok) *ok = d.isValid(); + return d; +} + //expects input of "x,y" QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok) { @@ -196,23 +247,6 @@ QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok) return QRectF(x, y, width, height); } -bool QmlStringConverters::boolFromString(const QString &str, bool *ok) -{ - if (str.isEmpty() || str == QLatin1String("false") || str == QLatin1String("0")) { - if (ok) - *ok = true; - return false; - } else if (str == QLatin1String("true") || str == QLatin1String("1")) { - if (ok) - *ok = true; - return true; - } - - if (ok) - *ok = false; - return true; -} - //expects input of "x,y,z" QVector3D QmlStringConverters::vector3DFromString(const QString &s, bool *ok) { diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h index 380a904..dfc59ce 100644 --- a/src/declarative/qml/qmlstringconverters_p.h +++ b/src/declarative/qml/qmlstringconverters_p.h @@ -70,11 +70,15 @@ QT_BEGIN_NAMESPACE namespace QmlStringConverters { QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &); + QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &, int preferredType, bool *ok = 0); + QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0); + QDate Q_DECLARATIVE_EXPORT dateFromString(const QString &, bool *ok = 0); + QTime Q_DECLARATIVE_EXPORT timeFromString(const QString &, bool *ok = 0); + QDateTime Q_DECLARATIVE_EXPORT dateTimeFromString(const QString &, bool *ok = 0); QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0); QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0); QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0); - bool Q_DECLARATIVE_EXPORT boolFromString(const QString &, bool *ok = 0); QVector3D Q_DECLARATIVE_EXPORT vector3DFromString(const QString &, bool *ok = 0); }; diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index 3e4b08c..14c8652 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -62,7 +62,7 @@ struct TypeNameData : public QScriptDeclarativeClass::Object { }; QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine) -: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), +: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), object(0), type(0) { } @@ -139,15 +139,17 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, return 0; } -QmlTypeNameScriptClass::Value QmlTypeNameScriptClass::property(Object *obj, const Identifier &name) +QmlTypeNameScriptClass::ScriptValue +QmlTypeNameScriptClass::property(Object *obj, const Identifier &name) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (type) { - return newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode); + return Value(scriptEngine, newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode)); } else if (object) { return ep->objectClass->property(object, name); } else { - return Value(&ep->scriptEngine, enumValue); + return Value(scriptEngine, enumValue); } } diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h index 702930f..cf8c621 100644 --- a/src/declarative/qml/qmltypenamescriptclass_p.h +++ b/src/declarative/qml/qmltypenamescriptclass_p.h @@ -56,14 +56,14 @@ #include <QtScript/qscriptclass.h> -#include <private/qscriptdeclarativeclass_p.h> +#include <private/qmlscriptclass_p.h> QT_BEGIN_NAMESPACE class QmlEngine; class QmlType; class QmlTypeNameCache; -class QmlTypeNameScriptClass : public QScriptDeclarativeClass +class QmlTypeNameScriptClass : public QmlScriptClass { public: QmlTypeNameScriptClass(QmlEngine *); @@ -77,7 +77,7 @@ protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual Value property(Object *, const Identifier &); + virtual ScriptValue property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 65a63f4..5e222a1 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -53,7 +53,7 @@ struct QmlValueTypeReference : public QScriptDeclarativeClass::Object { }; QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) -: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) { } @@ -98,7 +98,7 @@ QmlValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name, return rv; } -QmlValueTypeScriptClass::Value QmlValueTypeScriptClass::property(Object *obj, const Identifier &) +QmlValueTypeScriptClass::ScriptValue QmlValueTypeScriptClass::property(Object *obj, const Identifier &) { QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj); @@ -106,7 +106,8 @@ QmlValueTypeScriptClass::Value QmlValueTypeScriptClass::property(Object *obj, co ref->type->read(ref->object, ref->property); QVariant rv = p.read(ref->type); - return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + return Value(scriptEngine, static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv)); } void QmlValueTypeScriptClass::setProperty(Object *obj, const Identifier &, diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h index 9214987..09af967 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass_p.h +++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h @@ -52,15 +52,15 @@ // // We mean it. // -#include <QtScript/qscriptclass.h> -#include <private/qscriptdeclarativeclass_p.h> + +#include <private/qmlscriptclass_p.h> QT_BEGIN_NAMESPACE class QmlEngine; class QmlValueType; -class QmlValueTypeScriptClass : public QScriptDeclarativeClass +class QmlValueTypeScriptClass : public QmlScriptClass { public: QmlValueTypeScriptClass(QmlEngine *); @@ -70,7 +70,7 @@ public: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual Value property(Object *, const Identifier &); + virtual ScriptValue property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); virtual QVariant toVariant(Object *, bool *ok = 0); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 06795a8..e9a0449 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -57,7 +57,7 @@ #include "qmlvmemetaobject_p.h" #include "qmlbinding_p.h" #include "qmlcontext_p.h" -#include "qmlbindingoptimizations_p.h" +#include "qmlcompiledbindings_p.h" #include "qmlglobal_p.h" #include "qmlscriptstring.h" @@ -173,7 +173,7 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, if (instr.init.contextCache != -1) cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); if (instr.init.compiledBinding != -1) - cp->optimizedBindings = new QmlOptimizedBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); + cp->optimizedBindings = new QmlCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); } break; @@ -627,23 +627,6 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, } break; - case QmlInstruction::StoreIdOptBinding: - { - int coreIndex = instr.assignIdOptBinding.property; - if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) - break; - - QObject *target = stack.top(); - - QmlBinding_Id *bind = - new QmlBinding_Id(target, instr.assignIdOptBinding.property, - ctxt, instr.assignIdOptBinding.id); - bindValues.append(bind); - bind->m_mePtr = &bindValues.values[bindValues.count - 1]; - bind->addToObject(target); - } - break; - case QmlInstruction::StoreValueSource: { QObject *obj = stack.pop(); diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp index a0d6ef0..75c5179 100644 --- a/src/declarative/qml/qmlworkerscript.cpp +++ b/src/declarative/qml/qmlworkerscript.cpp @@ -51,6 +51,9 @@ #include <QtCore/qwaitcondition.h> #include <QtScript/qscriptvalueiterator.h> #include <QtCore/qfile.h> +#include <QtDeclarative/qmlinfo.h> + +QT_BEGIN_NAMESPACE class WorkerDataEvent : public QEvent { @@ -144,6 +147,82 @@ private: void processLoad(int, const QUrl &); }; +// Currently this will leak as no-one releases it in the worker thread +class QmlWorkerListModelAgent : public QObject +{ + Q_OBJECT + Q_PROPERTY(int count READ count); + +public: + QmlWorkerListModelAgent(QmlWorkerListModel *); + ~QmlWorkerListModelAgent(); + + void addref(); + void release(); + + int count() const; + + Q_INVOKABLE void clear(); + Q_INVOKABLE void remove(int index); + Q_INVOKABLE void append(const QScriptValue &); + Q_INVOKABLE void insert(int index, const QScriptValue&); + Q_INVOKABLE QScriptValue get(int index) const; + Q_INVOKABLE void set(int index, const QScriptValue &); + Q_INVOKABLE void sync(); + + struct VariantRef + { + VariantRef() : a(0) {} + VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); } + VariantRef(QmlWorkerListModelAgent *_a) : a(_a) { if (a) a->addref(); } + ~VariantRef() { if (a) a->release(); } + + VariantRef &operator=(const VariantRef &o) { + if (o.a) o.a->addref(); + if (a) a->release(); a = o.a; + return *this; + } + + QmlWorkerListModelAgent *a; + }; +protected: + virtual bool event(QEvent *); + +private: + friend class QmlWorkerScriptEnginePrivate; + friend class QmlWorkerListModel; + QScriptEngine *m_engine; + + struct Change { + enum { Inserted, Removed, Moved, Changed } type; + int index; // Inserted/Removed/Moved/Changed + int count; // Inserted/Removed/Moved/Changed + int to; // Moved + }; + + struct Data { + QHash<int, QString> roles; + QHash<QString, int> strings; + QList<QHash<int, QVariant> > values; + QList<Change> changes; + + void clearChange(); + void insertChange(int index, int count); + void removeChange(int index, int count); + void changedChange(int index, int count); + }; + Data data; + + struct Sync : public QEvent { + Sync() : QEvent(QEvent::User) {} + Data data; + }; + + QAtomicInt m_ref; + QmlWorkerListModel *m_model; +}; +Q_DECLARE_METATYPE(QmlWorkerListModelAgent::VariantRef); + QmlWorkerScriptEnginePrivate::QmlWorkerScriptEnginePrivate() : workerEngine(0), m_nextId(0) { @@ -285,6 +364,15 @@ QVariant QmlWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue & } return QVariant(list); + } else if (value.isQObject()) { + QmlWorkerListModel *lm = qobject_cast<QmlWorkerListModel *>(value.toQObject()); + if (lm) { + QmlWorkerListModelAgent::VariantRef v(lm->agent()); + return qVariantFromValue(v); + } else { + // No other QObject's are allowed to be sent + return QVariant(); + } } else if (value.isObject()) { QVariantHash hash; @@ -310,6 +398,15 @@ QScriptValue QmlWorkerScriptEnginePrivate::variantToScriptValue(const QVariant & return QScriptValue(value.toString()); } else if (value.userType() == QMetaType::QReal) { return QScriptValue(value.toReal()); + } else if (value.userType() == qMetaTypeId<QmlWorkerListModelAgent::VariantRef>()) { + QmlWorkerListModelAgent::VariantRef vr = qvariant_cast<QmlWorkerListModelAgent::VariantRef>(value); + if (vr.a->m_engine == 0) + vr.a->m_engine = engine; + else if (vr.a->m_engine != engine) + return engine->nullValue(); + QScriptValue o = engine->newQObject(vr.a); + o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc + return o; } else if (value.userType() == QMetaType::QVariantList) { QVariantList list = qvariant_cast<QVariantList>(value); QScriptValue rv = engine->newArray(list.count()); @@ -513,5 +610,411 @@ bool QmlWorkerScript::event(QEvent *event) } } - QML_DEFINE_TYPE(Qt, 4, 6, WorkerScript, QmlWorkerScript); + +void QmlWorkerListModelAgent::Data::clearChange() +{ + changes.clear(); +} + +void QmlWorkerListModelAgent::Data::insertChange(int index, int count) +{ + Change c = { Change::Inserted, index, count, 0 }; + changes << c; +} + +void QmlWorkerListModelAgent::Data::removeChange(int index, int count) +{ + Change c = { Change::Removed, index, count, 0 }; + changes << c; +} + +void QmlWorkerListModelAgent::Data::changedChange(int index, int count) +{ + Change c = { Change::Changed, index, count, 0 }; + changes << c; +} + +QmlWorkerListModelAgent::QmlWorkerListModelAgent(QmlWorkerListModel *m) +: m_engine(0), m_ref(1), m_model(m) +{ + data.roles = m_model->m_roles; + data.strings = m_model->m_strings; + data.values = m_model->m_values; +} + +QmlWorkerListModelAgent::~QmlWorkerListModelAgent() +{ +} + +void QmlWorkerListModelAgent::addref() +{ + m_ref.ref(); +} + +void QmlWorkerListModelAgent::release() +{ + bool del = !m_ref.deref(); + + if (del) + delete this; +} + +int QmlWorkerListModelAgent::count() const +{ + return data.values.count(); +} + +void QmlWorkerListModelAgent::clear() +{ + data.clearChange(); + data.removeChange(0, data.values.count()); + data.values.clear(); +} + +void QmlWorkerListModelAgent::remove(int index) +{ + if (data.values.count() <= index) + return; + + data.values.removeAt(index); + data.removeChange(index, 1); +} + +void QmlWorkerListModelAgent::append(const QScriptValue &value) +{ + QHash<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + data.values.append(row); + data.insertChange(data.values.count() - 1, 1); +} + +void QmlWorkerListModelAgent::insert(int index, const QScriptValue &value) +{ + if (index > data.values.count()) + return; + + QHash<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + data.values.insert(index, row); + data.insertChange(index, 1); +} + +void QmlWorkerListModelAgent::set(int index, const QScriptValue &value) +{ + if (data.values.count() <= index) + return; + + QHash<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + if (data.values.at(index) != row) { + data.values[index] = row; + data.changedChange(index, 1); + } +} + +QScriptValue QmlWorkerListModelAgent::get(int index) const +{ + if (data.values.count() <= index) + return m_engine->undefinedValue(); + + QScriptValue rv = m_engine->newObject(); + + QHash<int, QVariant> row = data.values.at(index); + for (QHash<int, QVariant>::ConstIterator iter = row.begin(); iter != row.end(); ++iter) + rv.setProperty(data.roles.value(iter.key()), qScriptValueFromValue(m_engine, iter.value())); + + return rv; +} + +void QmlWorkerListModelAgent::sync() +{ + Sync *s = new Sync; + s->data = data; + data.changes.clear(); + QCoreApplication::postEvent(this, s); +} + +bool QmlWorkerListModelAgent::event(QEvent *e) +{ + if (e->type() == QEvent::User) { + Sync *s = static_cast<Sync *>(e); + + const QList<Change> &changes = s->data.changes; + + if (m_model) { + bool cc = m_model->m_values.count() != s->data.values.count(); + + m_model->m_roles = s->data.roles; + m_model->m_strings = s->data.strings; + m_model->m_values = s->data.values; + + for (int ii = 0; ii < changes.count(); ++ii) { + const Change &change = changes.at(ii); + switch (change.type) { + case Change::Inserted: + emit m_model->itemsInserted(change.index, change.count); + break; + case Change::Removed: + emit m_model->itemsRemoved(change.index, change.count); + break; + case Change::Moved: + emit m_model->itemsMoved(change.index, change.to, change.count); + break; + case Change::Changed: + emit m_model->itemsMoved(change.index, change.to, change.count); + break; + } + } + + if (cc) + emit m_model->countChanged(); + } + } + + return QObject::event(e); +} + +QmlWorkerListModel::QmlWorkerListModel(QObject *parent) +: QListModelInterface(parent), m_agent(0) +{ +} + +QmlWorkerListModel::~QmlWorkerListModel() +{ + if (m_agent) { + m_agent->m_model = 0; + m_agent->release(); + } +} + +void QmlWorkerListModel::clear() +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + int count = m_values.count(); + m_values.clear(); + if (count) { + emit itemsRemoved(0, count); + emit countChanged(); + } +} + +void QmlWorkerListModel::remove(int index) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (m_values.count() <= index) + return; + + m_values.removeAt(index); + emit itemsRemoved(index, 1); + emit countChanged(); +} + +void QmlWorkerListModel::append(const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + QHash<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + m_values.append(data); + + emit itemsInserted(m_values.count() - 1, 1); + emit countChanged(); +} + +void QmlWorkerListModel::insert(int index, const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (index > m_values.count()) + return; + + QHash<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + m_values.insert(index, data); + emit itemsInserted(index, 1); + emit countChanged(); +} + +QScriptValue QmlWorkerListModel::get(int index) const +{ + QmlEngine *engine = qmlEngine(this); + if (!engine || m_values.count() <= index) + return QScriptValue(); + + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QScriptValue rv = scriptEngine->newObject(); + + QHash<int, QVariant> data = m_values.at(index); + for (QHash<int, QVariant>::ConstIterator iter = data.begin(); iter != data.end(); ++iter) + rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value())); + + return rv; +} + +void QmlWorkerListModel::set(int index, const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (m_values.count() <= index) + return; + + QHash<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + if (m_values.at(index) != data) { + m_values[index] = data; + emit itemsChanged(index, 1, m_roles.keys()); + } +} + +QmlWorkerListModelAgent *QmlWorkerListModel::agent() +{ + if (!m_agent) + m_agent = new QmlWorkerListModelAgent(this); + + return m_agent; +} + +QList<int> QmlWorkerListModel::roles() const +{ + return m_roles.keys(); +} + +QString QmlWorkerListModel::toString(int role) const +{ + return m_roles.value(role); +} + +int QmlWorkerListModel::count() const +{ + return m_values.count(); +} + +QHash<int,QVariant> QmlWorkerListModel::data(int index, const QList<int> &) const +{ + if (m_values.count() <= index) + return QHash<int, QVariant>(); + else + return m_values.at(index); +} + +QVariant QmlWorkerListModel::data(int index, int role) const +{ + if (m_values.count() <= index) + return QVariant(); + else + return m_values.at(index).value(role); +} + +QML_DEFINE_TYPE(Qt,4,6,WorkerListModel,QmlWorkerListModel) + +#include "qmlworkerscript.moc" + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlworkerscript_p.h b/src/declarative/qml/qmlworkerscript_p.h index 1ec7af3..f0ef7c9 100644 --- a/src/declarative/qml/qmlworkerscript_p.h +++ b/src/declarative/qml/qmlworkerscript_p.h @@ -55,11 +55,14 @@ #include "qml.h" #include "qmlparserstatus.h" +#include <private/qlistmodelinterface_p.h> #include <QtCore/qthread.h> #include <QtScript/qscriptvalue.h> #include <QtCore/qurl.h> +QT_BEGIN_NAMESPACE + class QmlWorkerScript; class QmlWorkerScriptEnginePrivate; class QmlWorkerScriptEngine : public QThread @@ -110,6 +113,48 @@ private: int m_scriptId; QUrl m_source; }; + +class QmlWorkerListModelAgent; +class QmlWorkerListModel : public QListModelInterface +{ + Q_OBJECT + Q_PROPERTY(int count READ count NOTIFY countChanged) + +public: + QmlWorkerListModel(QObject * = 0); + virtual ~QmlWorkerListModel(); + + Q_INVOKABLE void clear(); + Q_INVOKABLE void remove(int index); + Q_INVOKABLE void append(const QScriptValue &); + Q_INVOKABLE void insert(int index, const QScriptValue&); + Q_INVOKABLE QScriptValue get(int index) const; + Q_INVOKABLE void set(int index, const QScriptValue &); + + QmlWorkerListModelAgent *agent(); + + virtual QList<int> roles() const; + virtual QString toString(int role) const; + virtual int count() const; + virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; + virtual QVariant data(int index, int role) const; + +Q_SIGNALS: + void countChanged(); + +private: + friend class QmlWorkerListModelAgent; + + QHash<int, QString> m_roles; + QHash<QString, int> m_strings; + QList<QHash<int, QVariant> > m_values; + + QmlWorkerListModelAgent *m_agent; +}; + +QT_END_NAMESPACE + QML_DECLARE_TYPE(QmlWorkerScript); +QML_DECLARE_TYPE(QmlWorkerListModel); #endif // QMLWORKERSCRIPT_P_H diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 4c5015d..efb4159 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -1032,15 +1032,26 @@ void QmlPropertyAction::transition(QmlStateActions &actions, QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; + bool hasExplicit = false; if (hasTarget && d->value.isValid()) { Action myAction; myAction.property = d->createProperty(target(), d->propertyName, this); if (myAction.property.isValid()) { myAction.toValue = d->value; data->actions << myAction; + hasExplicit = true; + for (int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + if (action.property.object() == myAction.property.object() && + myAction.property.name() == action.property.name()) { + modified << action.property; + break; //### any chance there could be multiples? + } + } } } + if (!hasExplicit) for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; @@ -1649,10 +1660,12 @@ void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, int type) \inherits Animation \brief The PropertyAnimation element allows you to animate property changes. - Animate a size property over 200ms, from its current size to 20-by-20: + Animate theObject's size property over 200ms, from its current size to 20-by-20: \code - PropertyAnimation { property: "size"; to: "20x20"; duration: 200 } + PropertyAnimation { target: theObject; property: "size"; to: "20x20"; duration: 200 } \endcode + + For an introduction to animation in QML, see \l{QML Animation}. */ QmlPropertyAnimation::QmlPropertyAnimation(QObject *parent) @@ -2219,6 +2232,7 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, data->interpolator = d->interpolator; data->reverse = direction == Backward ? true : false; + bool hasExplicit = false; //an explicit animation has been specified if (hasTarget && d->toIsDefined) { Action myAction; @@ -2231,9 +2245,19 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); myAction.toValue = d->to; data->actions << myAction; + hasExplicit = true; + for (int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + if (action.property.object() == myAction.property.object() && + myAction.property.name() == action.property.name()) { + modified << action.property; + break; //### any chance there could be multiples? + } + } } } + if (!hasExplicit) for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp index f5fbd3f..800fd6b 100644 --- a/src/declarative/util/qmlconnection.cpp +++ b/src/declarative/util/qmlconnection.cpp @@ -172,7 +172,7 @@ void QmlConnection::connectIfValid() if (lparen >= 0 && d->signal.length() > lparen+2) { QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(',')); foreach (const QString &s, l) { - sigparams.append(s.toUtf8()); + sigparams.append(s.trimmed().toUtf8()); } } QString signalname = d->signal.left(lparen); diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index de6ee2e..8c70539 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -265,6 +265,7 @@ struct ModelNode QmlListModel *modelCache; ModelObject *objectCache; + bool isArray; }; QT_END_NAMESPACE @@ -280,6 +281,7 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap) { ModelNode *value = new ModelNode; QScriptValue v = it.value(); if (v.isArray()) { + value->isArray = true; value->setListValue(v); } else { value->values << v.toVariant(); @@ -296,6 +298,7 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { ModelNode *value = new ModelNode; QScriptValue v = it.value(); if (v.isArray()) { + value->isArray = true; value->setListValue(v); } else if (v.isObject()) { value->setObjectValue(v); @@ -367,27 +370,29 @@ QVariant QmlListModel::valueForNode(ModelNode *node) const { QObject *rv = 0; - if (!node->properties.isEmpty()) { - // Object - rv = node->object(this); - } else if (node->values.count() == 0) { - // Invalid - return QVariant(); - } else if (node->values.count() == 1) { - // Value - QVariant &var = node->values[0]; - ModelNode *valueNode = qvariant_cast<ModelNode *>(var); - if (valueNode) { - if (!valueNode->properties.isEmpty()) - rv = valueNode->object(this); - else - rv = valueNode->model(this); - } else { - return var; - } - } else if (node->values.count() > 1) { + if (node->isArray) { // List rv = node->model(this); + } else { + if (!node->properties.isEmpty()) { + // Object + rv = node->object(this); + } else if (node->values.count() == 0) { + // Invalid + return QVariant(); + } else if (node->values.count() == 1) { + // Value + QVariant &var = node->values[0]; + ModelNode *valueNode = qvariant_cast<ModelNode *>(var); + if (valueNode) { + if (!valueNode->properties.isEmpty()) + rv = valueNode->object(this); + else + rv = valueNode->model(this); + } else { + return var; + } + } } if (rv) @@ -400,7 +405,7 @@ QHash<int,QVariant> QmlListModel::data(int index, const QList<int> &roles) const { checkRoles(); QHash<int, QVariant> rv; - if (index >= count()) + if (index >= count() || index < 0) return rv; ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); @@ -425,7 +430,7 @@ QVariant QmlListModel::data(int index, int role) const { checkRoles(); QVariant rv; - if (index >= count()) + if (index >= count() || index < 0) return rv; ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); @@ -638,7 +643,7 @@ void QmlListModel::append(const QScriptValue& valuemap) */ QScriptValue QmlListModel::get(int index) const { - if (index >= count()) { + if (index >= count() || index < 0) { qmlInfo(this) << tr("get: index %1 out of range").arg(index); return 0; } @@ -675,7 +680,7 @@ void QmlListModel::set(int index, const QScriptValue& valuemap) qmlInfo(this) << tr("set: value is not an object"); return; } - if ( !_root || index > _root->values.count()) { + if ( !_root || index > _root->values.count() || index < 0) { qmlInfo(this) << tr("set: index %1 out of range").arg(index); return; } @@ -700,7 +705,7 @@ void QmlListModel::set(int index, const QScriptValue& valuemap) } /*! - \qmlmethod ListModel::set(int index, string property, variant value) + \qmlmethod ListModel::setProperty(int index, string property, variant value) Changes the \a property of the item at \a index in the list model to \a value. @@ -712,9 +717,9 @@ void QmlListModel::set(int index, const QScriptValue& valuemap) \sa append() */ -void QmlListModel::set(int index, const QString& property, const QVariant& value) +void QmlListModel::setProperty(int index, const QString& property, const QVariant& value) { - if ( !_root || index >= _root->values.count()) { + if ( !_root || index >= _root->values.count() || index < 0) { qmlInfo(this) << tr("set: index %1 out of range").arg(index); return; } @@ -738,6 +743,9 @@ public: QByteArray compile(const QList<QmlCustomParserProperty> &); bool compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data); void setCustomData(QObject *, const QByteArray &); + +private: + bool definesEmptyList(const QString &); }; bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data) @@ -857,6 +865,8 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) QStack<ModelNode *> nodes; nodes << root; + bool processingSet = false; + const ListModelData *lmd = (const ListModelData *)d.constData(); const char *data = ((const char *)lmd) + lmd->dataOffset; @@ -870,6 +880,8 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) ModelNode *n2 = new ModelNode; n->values << qVariantFromValue(n2); nodes.push(n2); + if (processingSet) + n->isArray = true; } break; @@ -880,7 +892,17 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) case ListInstruction::Value: { ModelNode *n = nodes.top(); - n->values.append(QString::fromUtf8(QByteArray(data + instr.dataIdx))); + QString s = QString::fromUtf8(QByteArray(data + instr.dataIdx)); + + bool isEmptyList = false; + if (!n->isArray) + isEmptyList = definesEmptyList(s); + if (isEmptyList) + n->isArray = true; + else + n->values.append(s); + + processingSet = false; } break; @@ -890,12 +912,26 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) ModelNode *n2 = new ModelNode; n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2); nodes.push(n2); + processingSet = true; } break; } } } +bool QmlListModelParser::definesEmptyList(const QString &s) +{ + if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) { + bool isEmptyList = true; + for (int i=1; i<s.length()-1; i++) { + if (!s[i].isSpace()) + return false; + } + return true; + } + return false; +} + QML_DEFINE_CUSTOM_TYPE(Qt, 4,6, ListModel, QmlListModel, QmlListModelParser) /*! @@ -933,7 +969,7 @@ static void dump(ModelNode *node, int ind) } ModelNode::ModelNode() -: modelCache(0), objectCache(0) +: modelCache(0), objectCache(0), isArray(false) { } diff --git a/src/declarative/util/qmllistmodel_p.h b/src/declarative/util/qmllistmodel_p.h index 47236d0..e18d3fd 100644 --- a/src/declarative/util/qmllistmodel_p.h +++ b/src/declarative/util/qmllistmodel_p.h @@ -80,7 +80,7 @@ public: Q_INVOKABLE void insert(int index, const QScriptValue&); Q_INVOKABLE QScriptValue get(int index) const; Q_INVOKABLE void set(int index, const QScriptValue&); - Q_INVOKABLE void set(int index, const QString& property, const QVariant& value); + Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value); Q_INVOKABLE void move(int from, int to, int count); Q_SIGNALS: diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp index f9238ca..3214dc8 100644 --- a/src/declarative/util/qmlpackage.cpp +++ b/src/declarative/util/qmlpackage.cpp @@ -42,6 +42,7 @@ #include "qmlpackage_p.h" #include <private/qobject_p.h> +#include "private/qmlguard_p.h" QT_BEGIN_NAMESPACE @@ -50,7 +51,28 @@ class QmlPackagePrivate : public QObjectPrivate public: QmlPackagePrivate() {} - QmlConcreteList<QObject *> dataList; + class DataList; + struct DataGuard : public QmlGuard<QObject> + { + DataGuard(QObject *obj, DataList *l) : list(l) { (QmlGuard<QObject>&)*this = obj; } + DataList *list; + void objectDestroyed(QObject *) { + // we assume priv will always be destroyed after objectDestroyed calls + list->removeOne(*this); + } + }; + + class DataList : public QList<DataGuard>, public QmlList<QObject*> + { + public: + virtual void append(QObject* v) { QList<DataGuard>::append(DataGuard(v, this)); } + virtual void insert(int i, QObject* v) { QList<DataGuard>::insert(i, DataGuard(v, this)); } + virtual void clear() { QList<DataGuard>::clear(); } + virtual QObject* at(int i) const { return QList<DataGuard>::at(i); } + virtual void removeAt(int i) { QList<DataGuard>::removeAt(i); } + virtual int count() const { return QList<DataGuard>::count(); } + }; + DataList dataList; }; class QmlPackageAttached : public QObject diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index 1f68512..5189118 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qmlpixmapcache_p.h" +#include "qmlnetworkaccessmanagerfactory.h" #include "qfxperf_p_p.h" @@ -57,112 +58,252 @@ #include <QWaitCondition> #include <QtCore/qdebug.h> #include <private/qobject_p.h> +#include <QSslError> + +#ifdef Q_OS_LINUX +#include <pthread.h> +#include <linux/sched.h> +#endif + +// Maximum number of simultaneous image requests to send. +static const int maxImageRequestCount = 8; QT_BEGIN_NAMESPACE +inline uint qHash(const QUrl &uri) +{ + return qHash(uri.toEncoded(QUrl::FormattingOption(0x100))); +} + class QmlImageReader : public QThread { Q_OBJECT public: - QmlImageReader(QObject *parent=0); + QmlImageReader(QmlEngine *eng); ~QmlImageReader(); - void read(QmlPixmapReply *rep); + QmlPixmapReply *getImage(const QUrl &url); void cancel(QmlPixmapReply *rep); + static QmlImageReader *instance(QmlEngine *engine); + protected: void run(); + bool event(QEvent *event); -private: - struct Job { - Job() : reply(0), error(false) {} - QmlPixmapReply *reply; - QImage img; - bool error; - }; +private slots: + void networkRequestDone(); + void namInvalidated() { + accessManagerValid = false; + } - void loadImage(Job &job); +private: + QNetworkAccessManager *networkAccessManager() { + if (!accessManagerValid) { + delete accessManager; + accessManager = 0; + } + if (!accessManager) { + if (engine && engine->networkAccessManagerFactory()) { + connect(engine->networkAccessManagerFactory(), SIGNAL(invalidated()) + , this, SLOT(namInvalidated()), Qt::UniqueConnection); + accessManager = engine->networkAccessManagerFactory()->create(this); + } else { + accessManager = new QNetworkAccessManager(this); + } + accessManagerValid = true; + } + return accessManager; + } - QList<Job> jobs; + QList<QmlPixmapReply*> jobs; + QList<QmlPixmapReply*> cancelled; + QHash<QNetworkReply*,QmlPixmapReply*> replies; + QNetworkAccessManager *accessManager; + bool accessManagerValid; + QmlEngine *engine; QMutex mutex; - QWaitCondition haveJob; - bool quit; + static QHash<QmlEngine *,QmlImageReader*> readers; }; -class QmlImageDecodeEvent : public QEvent +QHash<QmlEngine *,QmlImageReader*> QmlImageReader::readers; + +class QmlImageReaderEvent : public QEvent { public: - QmlImageDecodeEvent(bool err, QImage &img) : QEvent(QEvent::User), error(err), image(img) {} + enum ReadError { NoError, Loading, Decoding }; + + QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, QImage &img) + : QEvent(QEvent::User), error(err), image(img) {} - bool error; + ReadError error; QImage image; }; -Q_GLOBAL_STATIC(QmlImageReader, qmlImageReader) - -QmlImageReader::QmlImageReader(QObject *parent) : QThread(parent), quit(false) +QmlImageReader::QmlImageReader(QmlEngine *eng) + : QThread(eng), accessManager(0), accessManagerValid(false), engine(eng) { start(QThread::LowPriority); } QmlImageReader::~QmlImageReader() { - quit = true; - haveJob.wakeOne(); } -void QmlImageReader::read(QmlPixmapReply *reply) +QmlImageReader *QmlImageReader::instance(QmlEngine *engine) +{ + QmlImageReader *reader = readers.value(engine); + if (!reader) { + static QMutex rmutex; + rmutex.lock(); + reader = new QmlImageReader(engine); + readers.insert(engine, reader); + rmutex.unlock(); + } + + return reader; +} + +QmlPixmapReply *QmlImageReader::getImage(const QUrl &url) { mutex.lock(); - Job job; - job.reply = reply; - jobs.append(job); + QmlPixmapReply *reply = new QmlPixmapReply(engine, url); + jobs.append(reply); if (jobs.count() == 1) - haveJob.wakeOne(); + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); mutex.unlock(); + return reply; } void QmlImageReader::cancel(QmlPixmapReply *reply) { mutex.lock(); - QList<Job>::iterator it = jobs.begin(); - while (it != jobs.end()) { - if ((*it).reply == reply) { - jobs.erase(it); - break; + if (reply->isLoading()) { + // Already requested. Add to cancel list to be cancelled in reader thread. + cancelled.append(reply); + if (cancelled.count() == 1) + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } else { + // Not yet processed - just remove from waiting list + QList<QmlPixmapReply*>::iterator it = jobs.begin(); + while (it != jobs.end()) { + QmlPixmapReply *job = *it; + if (job == reply) { + jobs.erase(it); + break; + } + ++it; } - ++it; } mutex.unlock(); } -void QmlImageReader::loadImage(Job &job) +void QmlImageReader::run() { - QImageReader imgio(job.reply->device()); - if (imgio.read(&job.img)) { - job.error = false; - } else { - job.error = true; - qWarning() << imgio.errorString(); +#ifdef Q_OS_LINUX + struct sched_param param; + int policy; + + pthread_getschedparam(pthread_self(), &policy, ¶m); + pthread_setschedparam(pthread_self(), SCHED_IDLE, ¶m); +#endif + + exec(); +} + +bool QmlImageReader::event(QEvent *event) +{ + if (event->type() == QEvent::User) { + static int replyDownloadProgress = -1; + static int replyFinished = -1; + static int downloadProgress = -1; + static int thisNetworkRequestDone = -1; + + if (replyDownloadProgress == -1) { + replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); + replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()"); + downloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); + thisNetworkRequestDone = QmlImageReader::staticMetaObject.indexOfSlot("networkRequestDone()"); + } + + while (1) { + mutex.lock(); + + if (cancelled.count()) { + for (int i = 0; i < cancelled.count(); ++i) { + QmlPixmapReply *job = cancelled.at(i); + QNetworkReply *reply = replies.key(job, 0); + if (reply && reply->isRunning()) { + replies.remove(reply); + reply->close(); + job->release(true); + } + } + cancelled.clear(); + } + + if (!accessManagerValid) { + // throw away existing requests and reschedule. + QHash<QNetworkReply*,QmlPixmapReply*>::iterator it = replies.begin(); + for (; it != replies.end(); ++it) { + delete it.key(); + jobs.prepend(*it); + } + replies.clear(); + } + + if (!jobs.count() || replies.count() > maxImageRequestCount) { + mutex.unlock(); + break; + } + + QmlPixmapReply *runningJob = jobs.takeFirst(); + runningJob->addRef(); + runningJob->setLoading(); + QUrl url = runningJob->url(); + mutex.unlock(); + + // fetch + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + QNetworkReply *reply = networkAccessManager()->get(req); + + QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress); + QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone); + + replies.insert(reply, runningJob); + } + return true; } + + return QObject::event(event); } -void QmlImageReader::run() +void QmlImageReader::networkRequestDone() { - while (1) { - mutex.lock(); - if (!jobs.count()) - haveJob.wait(&mutex); - if (quit) - break; - Job runningJob = jobs.takeFirst(); - runningJob.reply->addRef(); - mutex.unlock(); - - loadImage(runningJob); - QCoreApplication::postEvent(runningJob.reply, new QmlImageDecodeEvent(runningJob.error, runningJob.img)); + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + QmlPixmapReply *job = replies.take(reply); + if (job) { + QImage image; + QmlImageReaderEvent::ReadError error; + if (reply->error()) { + error = QmlImageReaderEvent::Loading; + } else { + QImageReader imgio(reply); + if (imgio.read(&image)) { + error = QmlImageReaderEvent::NoError; + } else { + error = QmlImageReaderEvent::Decoding; + } + } + // send completion event to the QmlPixmapReply + QCoreApplication::postEvent(job, new QmlImageReaderEvent(error, image)); } + // kick off event loop again if we have dropped below max request count + if (replies.count() == maxImageRequestCount) + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + reply->deleteLater(); } static bool readImage(QIODevice *dev, QPixmap *pixmap) @@ -215,85 +356,55 @@ static QString toLocalFileOrQrc(const QUrl& url) return r; } -typedef QHash<QString, QmlPixmapReply *> QmlPixmapReplyHash; -static QmlPixmapReplyHash qmlActivePixmapReplies; +typedef QHash<QUrl, QmlPixmapReply *> QmlPixmapReplyHash; +Q_GLOBAL_STATIC(QmlPixmapReplyHash, qmlActivePixmapReplies); class QmlPixmapReplyPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QmlPixmapReply) public: - QmlPixmapReplyPrivate(const QString &url, QNetworkReply *r) - : QObjectPrivate(), refCount(1), urlKey(url), reply(r), status(QmlPixmapReply::Loading) { + QmlPixmapReplyPrivate(QmlEngine *e, const QUrl &u) + : QObjectPrivate(), refCount(1), url(u), status(QmlPixmapReply::Loading), loading(false), engine(e) { } int refCount; - QString urlKey; - QNetworkReply *reply; + QUrl url; QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard - QImage image; QmlPixmapReply::Status status; + bool loading; + QmlEngine *engine; }; -QmlPixmapReply::QmlPixmapReply(const QString &key, QNetworkReply *reply) - : QObject(*new QmlPixmapReplyPrivate(key, reply), 0) +QmlPixmapReply::QmlPixmapReply(QmlEngine *engine, const QUrl &url) + : QObject(*new QmlPixmapReplyPrivate(engine, url), 0) { - Q_D(QmlPixmapReply); - - static int replyDownloadProgress = -1; - static int replyFinished = -1; - static int thisDownloadProgress = -1; - static int thisNetworkRequestDone = -1; - - if (replyDownloadProgress == -1) { - replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); - replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()"); - thisDownloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); - thisNetworkRequestDone = QmlPixmapReply::staticMetaObject.indexOfSlot("networkRequestDone()"); - } - - QMetaObject::connect(d->reply, replyDownloadProgress, this, thisDownloadProgress, Qt::DirectConnection); - QMetaObject::connect(d->reply, replyFinished, this, thisNetworkRequestDone); } QmlPixmapReply::~QmlPixmapReply() { - Q_D(QmlPixmapReply); - if (d->status == Decoding) - qmlImageReader()->cancel(this); - delete d->reply; } -void QmlPixmapReply::networkRequestDone() +const QUrl &QmlPixmapReply::url() const { - Q_D(QmlPixmapReply); - if (d->reply->error()) { - d->pixmap = QPixmap(); - d->status = Error; - QPixmapCache::insert(d->urlKey, d->pixmap); - qWarning() << "Network error loading" << d->urlKey << d->reply->errorString(); - emit finished(); - } else { - qmlImageReader()->read(this); - d->status = Decoding; - } + Q_D(const QmlPixmapReply); + return d->url; } bool QmlPixmapReply::event(QEvent *event) { Q_D(QmlPixmapReply); if (event->type() == QEvent::User) { + d->loading = false; if (!release(true)) { - QmlImageDecodeEvent *de = static_cast<QmlImageDecodeEvent*>(event); - d->status = de->error ? Error : Ready; - if (d->status == Ready) { + QmlImageReaderEvent *de = static_cast<QmlImageReaderEvent*>(event); + d->status = (de->error == QmlImageReaderEvent::NoError) ? Ready : Error; + if (d->status == Ready) d->pixmap = QPixmap::fromImage(de->image); - d->image = QImage(); - } else { - qWarning() << "Error decoding" << d->urlKey; - } - QPixmapCache::insert(d->urlKey, d->pixmap); // note: may fail (returns false) + QByteArray key = d->url.toEncoded(QUrl::FormattingOption(0x100)); + QString strKey = QString::fromLatin1(key.constData(), key.count()); + QPixmapCache::insert(strKey, d->pixmap); // note: may fail (returns false) emit finished(); } return true; @@ -308,10 +419,16 @@ QmlPixmapReply::Status QmlPixmapReply::status() const return d->status; } -QIODevice *QmlPixmapReply::device() +bool QmlPixmapReply::isLoading() const +{ + Q_D(const QmlPixmapReply); + return d->loading; +} + +void QmlPixmapReply::setLoading() { Q_D(QmlPixmapReply); - return d->reply; + d->loading = true; } void QmlPixmapReply::addRef() @@ -326,12 +443,18 @@ bool QmlPixmapReply::release(bool defer) Q_ASSERT(d->refCount > 0); --d->refCount; if (d->refCount == 0) { - qmlActivePixmapReplies.remove(d->urlKey); + qmlActivePixmapReplies()->remove(d->url); + if (d->status == Loading && !d->loading) + QmlImageReader::instance(d->engine)->cancel(this); if (defer) deleteLater(); else delete this; return true; + } else if (d->refCount == 1 && d->loading) { + // The only reference left is the reader thread. + qmlActivePixmapReplies()->remove(d->url); + QmlImageReader::instance(d->engine)->cancel(this); } return false; @@ -373,22 +496,22 @@ QmlPixmapReply::Status QmlPixmapCache::get(const QUrl& url, QPixmap *pixmap) } #endif - QString key = url.toString(); - - QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); - if (iter != qmlActivePixmapReplies.end() && (*iter)->status() == QmlPixmapReply::Ready) { + QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100)); + QString strKey = QString::fromLatin1(key.constData(), key.count()); + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); + if (iter != qmlActivePixmapReplies()->end() && (*iter)->status() == QmlPixmapReply::Ready) { // Must check this, since QPixmapCache::insert may have failed. *pixmap = (*iter)->d_func()->pixmap; status = (*iter)->status(); (*iter)->release(); - } else if (QPixmapCache::find(key, pixmap)) { - if (iter != qmlActivePixmapReplies.end()) { + } else if (QPixmapCache::find(strKey, pixmap)) { + if (iter != qmlActivePixmapReplies()->end()) { status = (*iter)->status(); (*iter)->release(); } else { status = pixmap->isNull() ? QmlPixmapReply::Error : QmlPixmapReply::Ready; } - } else if (iter != qmlActivePixmapReplies.end()) { + } else if (iter != qmlActivePixmapReplies()->end()) { status = QmlPixmapReply::Loading; } @@ -406,13 +529,11 @@ QmlPixmapReply::Status QmlPixmapCache::get(const QUrl& url, QPixmap *pixmap) */ QmlPixmapReply *QmlPixmapCache::request(QmlEngine *engine, const QUrl &url) { - QString key = url.toString(); - QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); - if (iter == qmlActivePixmapReplies.end()) { - QNetworkRequest req(url); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - QmlPixmapReply *item = new QmlPixmapReply(key, engine->networkAccessManager()->get(req)); - iter = qmlActivePixmapReplies.insert(key, item); + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); + if (iter == qmlActivePixmapReplies()->end()) { + QmlImageReader *reader = QmlImageReader::instance(engine); + QmlPixmapReply *item = reader->getImage(url); + iter = qmlActivePixmapReplies()->insert(url, item); } else { (*iter)->addRef(); } @@ -430,9 +551,8 @@ QmlPixmapReply *QmlPixmapCache::request(QmlEngine *engine, const QUrl &url) */ void QmlPixmapCache::cancel(const QUrl& url, QObject *obj) { - QString key = url.toString(); - QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); - if (iter == qmlActivePixmapReplies.end()) + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); + if (iter == qmlActivePixmapReplies()->end()) return; QmlPixmapReply *reply = *iter; @@ -447,7 +567,7 @@ void QmlPixmapCache::cancel(const QUrl& url, QObject *obj) */ int QmlPixmapCache::pendingRequests() { - return qmlActivePixmapReplies.count(); + return qmlActivePixmapReplies()->count(); } #include <qmlpixmapcache.moc> diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h index 4dcafcf..0140352 100644 --- a/src/declarative/util/qmlpixmapcache_p.h +++ b/src/declarative/util/qmlpixmapcache_p.h @@ -59,12 +59,14 @@ class Q_DECLARATIVE_EXPORT QmlPixmapReply : public QObject { Q_OBJECT public: - QmlPixmapReply(const QString &key, QNetworkReply *reply); + QmlPixmapReply(QmlEngine *engine, const QUrl &url); ~QmlPixmapReply(); - enum Status { Ready, Error, Unrequested, Loading, Decoding }; + enum Status { Ready, Error, Unrequested, Loading }; Status status() const; + const QUrl &url() const; + Q_SIGNALS: void finished(); void downloadProgress(qint64, qint64); @@ -73,12 +75,10 @@ protected: bool event(QEvent *event); private: - QIODevice *device(); void addRef(); bool release(bool defer=false); - -private Q_SLOTS: - void networkRequestDone(); + bool isLoading() const; + void setLoading(); private: Q_DISABLE_COPY(QmlPixmapReply) diff --git a/src/declarative/util/qmlpropertymap.cpp b/src/declarative/util/qmlpropertymap.cpp index d0a0428..226f82e 100644 --- a/src/declarative/util/qmlpropertymap.cpp +++ b/src/declarative/util/qmlpropertymap.cpp @@ -118,7 +118,7 @@ void QmlPropertyMapMetaObject::propertyWrite(int index) key will be updated as well. To detect value changes made in the UI layer you can connect to the valueChanged() signal. - However, note that valueChanged() is \b NOT emitted when changes are made by calling insert() + However, note that valueChanged() is \bold NOT emitted when changes are made by calling insert() or clear() - it is only emitted when a value is updated from QML. \note It is not possible to remove keys from the map; once a key has been added, you can only @@ -270,6 +270,9 @@ const QVariant QmlPropertyMap::operator[](const QString &key) const \fn void QmlPropertyMap::valueChanged(const QString &key) This signal is emitted whenever one of the values in the map is changed. \a key is the key corresponding to the value that was changed. + + \note valueChanged() is \bold NOT emitted when changes are made by calling insert() + or clear() - it is only emitted when a value is updated from QML. */ QT_END_NAMESPACE diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index e41cbaf..6a5b82a 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -451,7 +451,8 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever qWarning() << " Action event:" << action.event->typeName(); else qWarning() << " Action:" << action.property.object() - << action.property.name() << action.fromValue << action.toValue; + << action.property.name() << "From:" << action.fromValue + << "To:" << action.toValue; } } diff --git a/src/declarative/util/qmlstateoperations_p.h b/src/declarative/util/qmlstateoperations_p.h index 87af7bb..75c17422 100644 --- a/src/declarative/util/qmlstateoperations_p.h +++ b/src/declarative/util/qmlstateoperations_p.h @@ -45,7 +45,7 @@ #include "qmlstate_p.h" #include <qmlgraphicsitem.h> -#include "../graphicsitems/qmlgraphicsanchors_p.h" +#include "private/qmlgraphicsanchors_p.h" #include <qmlscriptstring.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlstyledtext.cpp b/src/declarative/util/qmlstyledtext.cpp index ce2b2ea..36b5e49 100644 --- a/src/declarative/util/qmlstyledtext.cpp +++ b/src/declarative/util/qmlstyledtext.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include <QXmlStreamReader> #include <QStack> #include <QVector> #include <QPainter> @@ -52,20 +51,22 @@ QmlStyledText supports few tags: <b></b> - bold + <i></i> - italic <br> - new line - <font color="color_name"></font> + <font color="color_name" size="1-7"></font> - The opening and closing tags may be correctly nested. + The opening and closing tags must be correctly nested. */ class QmlStyledTextPrivate { public: - QmlStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l) {} + QmlStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l), baseFont(layout.font()) {} void parse(); bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format); bool parseCloseTag(const QChar *&ch, const QString &textIn); + void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut); bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format); QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn); QStringRef parseValue(const QChar *&ch, const QString &textIn); @@ -77,6 +78,7 @@ public: QString text; QTextLayout &layout; + QFont baseFont; static const QChar lessThan; static const QChar greaterThan; @@ -84,6 +86,7 @@ public: static const QChar singleQuote; static const QChar doubleQuote; static const QChar slash; + static const QChar ampersand; }; const QChar QmlStyledTextPrivate::lessThan(QLatin1Char('<')); @@ -92,6 +95,7 @@ const QChar QmlStyledTextPrivate::equals(QLatin1Char('=')); const QChar QmlStyledTextPrivate::singleQuote(QLatin1Char('\'')); const QChar QmlStyledTextPrivate::doubleQuote(QLatin1Char('\"')); const QChar QmlStyledTextPrivate::slash(QLatin1Char('/')); +const QChar QmlStyledTextPrivate::ampersand(QLatin1Char('&')); QmlStyledText::QmlStyledText(const QString &string, QTextLayout &layout) : d(new QmlStyledTextPrivate(string, layout)) @@ -109,66 +113,6 @@ void QmlStyledText::parse(const QString &string, QTextLayout &layout) styledText.d->parse(); } -#define CUSTOM_PARSER - -#ifndef CUSTOM_PARSER -void QmlStyledTextPrivate::parse() -{ - QList<QTextLayout::FormatRange> ranges; - QStack<QTextCharFormat> formatStack; - - QString drawText; - drawText.reserve(text.count()); - - QXmlStreamReader xml("<html>" + text + "</html>"); - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::StartElement) { - QStringRef name = xml.name(); - if (name == "b") { - QTextCharFormat format; - if (formatStack.count()) - format = formatStack.top(); - else - format.setFont(layout.font()); - format.setFontWeight(QFont::Bold); - formatStack.push(format); - } else if (name == "br") { - drawText.append(QChar(QChar::LineSeparator)); - } else if (name == "font") { - QTextCharFormat format; - if (formatStack.count()) - format = formatStack.top(); - else - format.setFont(layout.font()); - QStringRef col = xml.attributes().value("color"); - if (!col.isEmpty()) { - format.setForeground(QColor(col.toString())); - formatStack.push(format); - } - } - } else if (xml.tokenType() == QXmlStreamReader::EndElement) { - if (formatStack.count() > 1) { - QStringRef name = xml.name(); - if (name == "b" || name == "font" || name == "br") - formatStack.pop(); - } - } else if (xml.tokenType() == QXmlStreamReader::Characters) { - if (formatStack.count() > 1) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = xml.text().length(); - ranges.append(formatRange); - } - drawText.append(xml.text()); - } - } - - layout.setText(drawText); - layout.setAdditionalFormats(ranges); -} -#else void QmlStyledTextPrivate::parse() { QList<QTextLayout::FormatRange> ranges; @@ -179,19 +123,20 @@ void QmlStyledTextPrivate::parse() int textStart = 0; int textLength = 0; + int rangeStart = 0; const QChar *ch = text.constData(); while (!ch->isNull()) { if (*ch == lessThan) { - if (textLength) { - if (formatStack.count()) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = textLength; - ranges.append(formatRange); - } + if (textLength) drawText.append(QStringRef(&text, textStart, textLength)); + if (rangeStart != drawText.length() && formatStack.count()) { + QTextLayout::FormatRange formatRange; + formatRange.format = formatStack.top(); + formatRange.start = rangeStart; + formatRange.length = drawText.length() - rangeStart; + ranges.append(formatRange); } + rangeStart = drawText.length(); ++ch; if (*ch == slash) { ++ch; @@ -202,33 +147,36 @@ void QmlStyledTextPrivate::parse() if (formatStack.count()) format = formatStack.top(); else - format.setFont(layout.font()); + format.setFont(baseFont); if (parseTag(ch, text, drawText, format)) formatStack.push(format); } textStart = ch - text.constData() + 1; textLength = 0; + } else if (*ch == ampersand) { + ++ch; + drawText.append(QStringRef(&text, textStart, textLength)); + parseEntity(ch, text, drawText); + textStart = ch - text.constData() + 1; + textLength = 0; } else { ++textLength; } ++ch; } - if (textLength) { - if (formatStack.count()) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = textLength; - ranges.append(formatRange); - } + if (textLength) drawText.append(QStringRef(&text, textStart, textLength)); + if (rangeStart != drawText.length() && formatStack.count()) { + QTextLayout::FormatRange formatRange; + formatRange.format = formatStack.top(); + formatRange.start = rangeStart; + formatRange.length = drawText.length() - rangeStart; + ranges.append(formatRange); } layout.setText(drawText); layout.setAdditionalFormats(ranges); } -#endif - bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format) { @@ -239,7 +187,8 @@ bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QSt while (!ch->isNull()) { if (*ch == greaterThan) { QStringRef tag(&textIn, tagStart, tagLength); - if (tag.at(0) == QLatin1Char('b')) { + const QChar char0 = tag.at(0); + if (char0 == QLatin1Char('b')) { if (tagLength == 1) { format.setFontWeight(QFont::Bold); return true; @@ -247,6 +196,11 @@ bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QSt textOut.append(QChar(QChar::LineSeparator)); return true; } + } else if (char0 == QLatin1Char('i')) { + if (tagLength == 1) { + format.setFontItalic(true); + return true; + } } return false; } else if (ch->isSpace()) { @@ -274,11 +228,15 @@ bool QmlStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn while (!ch->isNull()) { if (*ch == greaterThan) { QStringRef tag(&textIn, tagStart, tagLength); - if (tag.at(0) == QLatin1Char('b')) { + const QChar char0 = tag.at(0); + if (char0 == QLatin1Char('b')) { if (tagLength == 1) return true; else if (tag.at(1) == QLatin1Char('r') && tagLength == 2) return true; + } else if (char0 == QLatin1Char('i')) { + if (tagLength == 1) + return true; } else if (tag == QLatin1String("font")) { return true; } @@ -292,6 +250,26 @@ bool QmlStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn return false; } +void QmlStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textIn, QString &textOut) +{ + int entityStart = ch - textIn.constData(); + int entityLength = 0; + while (!ch->isNull()) { + if (*ch == QLatin1Char(';')) { + QStringRef entity(&textIn, entityStart, entityLength); + if (entity == QLatin1String("gt")) + textOut += QChar(62); + else if (entity == QLatin1String("lt")) + textOut += QChar(60); + else if (entity == QLatin1String("amp")) + textOut += QChar(38); + return; + } + ++entityLength; + ++ch; + } +} + bool QmlStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format) { bool valid = false; @@ -301,6 +279,15 @@ bool QmlStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString & if (attr.first == QLatin1String("color")) { valid = true; format.setForeground(QColor(attr.second.toString())); + } else if (attr.first == QLatin1String("size")) { + valid = true; + int size = attr.second.toString().toInt(); + if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+')) + size += 3; + if (size >= 1 && size <= 7) { + static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 }; + format.setFontPointSize(baseFont.pointSize() * scaling[size-1]); + } } } while (!ch->isNull() && !attr.first.isEmpty()); diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index bb935d0..e2a25c5 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -247,7 +247,8 @@ void QmlTransitionManager::transition(const QList<Action> &list, qWarning() << " No transition for event:" << action.event->typeName(); else qWarning() << " No transition for:" << action.property.object() - << action.property.name() << action.fromValue << action.toValue; + << action.property.name() << "From:" << action.fromValue + << "To:" << action.toValue; } } if (!transition) diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp index e9031ac..83ecc30 100644 --- a/src/gui/dialogs/qcolordialog.cpp +++ b/src/gui/dialogs/qcolordialog.cpp @@ -68,6 +68,10 @@ #include "private/qt_s60_p.h" #endif +#if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5) +# define QT_SMALL_COLORDIALOG +#endif + QT_BEGIN_NAMESPACE //////////// QWellArray BEGIN @@ -1072,14 +1076,17 @@ QColorShower::QColorShower(QColorDialog *parent) gl->setMargin(gl->spacing()); lab = new QColorShowLabel(this); -#ifdef Q_WS_S60 +#ifdef QT_SMALL_COLORDIALOG +# ifdef Q_WS_S60 QS60Data s60Data = QS60Data(); const bool nonTouchUI = !s60Data.hasTouchscreen; +# elif defined Q_WS_MAEMO_5 + const bool nonTouchUI = false; +# endif #endif - #ifndef Q_WS_WINCE -#ifdef Q_WS_S60 +#ifdef QT_SMALL_COLORDIALOG lab->setMinimumHeight(60); #endif lab->setMinimumWidth(60); @@ -1090,7 +1097,7 @@ QColorShower::QColorShower(QColorDialog *parent) // In S60, due to small screen and different screen layouts need to re-arrange the widgets. // For QVGA screens only the comboboxes and color label are visible. // For nHD screens only color and luminence pickers and color label are visible. -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lab, 0, 0, -1, 1); #else if (nonTouchUI) @@ -1108,7 +1115,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblHue->setBuddy(hEd); #endif lblHue->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblHue, 0, 1); gl->addWidget(hEd, 0, 2); #else @@ -1127,7 +1134,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblSat->setBuddy(sEd); #endif lblSat->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblSat, 1, 1); gl->addWidget(sEd, 1, 2); #else @@ -1146,7 +1153,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblVal->setBuddy(vEd); #endif lblVal->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblVal, 2, 1); gl->addWidget(vEd, 2, 2); #else @@ -1165,7 +1172,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblRed->setBuddy(rEd); #endif lblRed->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblRed, 0, 3); gl->addWidget(rEd, 0, 4); #else @@ -1184,7 +1191,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblGreen->setBuddy(gEd); #endif lblGreen->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblGreen, 1, 3); gl->addWidget(gEd, 1, 4); #else @@ -1203,7 +1210,7 @@ QColorShower::QColorShower(QColorDialog *parent) lblBlue->setBuddy(bEd); #endif lblBlue->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(lblBlue, 2, 3); gl->addWidget(bEd, 2, 4); #else @@ -1222,7 +1229,7 @@ QColorShower::QColorShower(QColorDialog *parent) alphaLab->setBuddy(alphaEd); #endif alphaLab->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -#ifndef Q_WS_S60 +#if !defined(QT_SMALL_COLORDIALOG) gl->addWidget(alphaLab, 3, 1, 1, 3); gl->addWidget(alphaEd, 3, 4); #else @@ -1467,7 +1474,7 @@ void QColorDialogPrivate::init(const QColor &initial) leftLay = 0; -#if (defined(Q_WS_WINCE) || defined(Q_WS_S60)) +#if defined(Q_WS_WINCE) || defined(QT_SMALL_COLORDIALOG) smallDisplay = true; const int lumSpace = 20; #else @@ -1497,9 +1504,13 @@ void QColorDialogPrivate::init(const QColor &initial) } #endif -#if defined(Q_WS_S60) +#if defined(QT_SMALL_COLORDIALOG) +# if defined(Q_WS_S60) QS60Data s60Data = QS60Data(); const bool nonTouchUI = !s60Data.hasTouchscreen; +# elif defined(Q_WS_MAEMO_5) + const bool nonTouchUI = false; +# endif #endif if (!smallDisplay) { @@ -1532,7 +1543,7 @@ void QColorDialogPrivate::init(const QColor &initial) leftLay->addWidget(addCusBt); } else { // better color picker size for small displays -#ifdef Q_WS_S60 +#if defined(QT_SMALL_COLORDIALOG) QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); pWidth = pHeight = qMin(screenSize.width(), screenSize.height()); pHeight -= 20; @@ -1558,7 +1569,7 @@ void QColorDialogPrivate::init(const QColor &initial) cp->setFrameStyle(QFrame::Panel + QFrame::Sunken); -#if defined(Q_WS_S60) +#if defined(QT_SMALL_COLORDIALOG) if (!nonTouchUI) { pickLay->addWidget(cp); cLay->addSpacing(lumSpace); @@ -1572,7 +1583,7 @@ void QColorDialogPrivate::init(const QColor &initial) cLay->addSpacing(lumSpace); lp = new QColorLuminancePicker(q); -#if defined(Q_WS_S60) +#if defined(QT_SMALL_COLORDIALOG) QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); const int minDimension = qMin(screenSize.height(), screenSize.width()); //set picker to be finger-usable @@ -1596,7 +1607,7 @@ void QColorDialogPrivate::init(const QColor &initial) QObject::connect(cs, SIGNAL(newCol(QRgb)), q, SLOT(_q_newColorTypedIn(QRgb))); QObject::connect(cs, SIGNAL(currentColorChanged(QColor)), q, SIGNAL(currentColorChanged(QColor))); -#if defined(Q_WS_S60) +#if defined(QT_SMALL_COLORDIALOG) if (!nonTouchUI) pWidth -= cp->size().width(); topLay->addWidget(cs); diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 3650051..9ff2ad8 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -265,6 +265,14 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f) if (!qt_wince_is_smartphone()) setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint)); #endif + +#ifdef Q_WS_S60 + if (S60->avkonComponentsSupportTransparency) { + bool noSystemBackground = testAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_TranslucentBackground); // also sets WA_NoSystemBackground + setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); // restore system background attribute + } +#endif } #ifdef QT3_SUPPORT @@ -294,6 +302,14 @@ QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f) if (!qt_wince_is_smartphone()) setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint)); #endif + +#ifdef Q_WS_S60 + if (S60->avkonComponentsSupportTransparency) { + bool noSystemBackground = testAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_TranslucentBackground); // also sets WA_NoSystemBackground + setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); // restore system background attribute + } +#endif } /*! diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 3d59463..21650bb 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -1222,12 +1222,6 @@ QFileDialog::ViewMode QFileDialog::viewMode() const void QFileDialog::setFileMode(QFileDialog::FileMode mode) { Q_D(QFileDialog); - if (d->nativeDialogInUse){ - d->model->setFilter(d->filterForMode(filter())); - d->setFilter_sys(); - return; - } - d->fileMode = mode; d->retranslateWindowTitle(); @@ -1263,6 +1257,11 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode) } } setLabelText(Accept, buttonText); + if (d->nativeDialogInUse){ + d->setFilter_sys(); + return; + } + d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly)); d->_q_updateOkButton(); } @@ -1300,6 +1299,10 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode) d->qFileDialogUi->lookInCombo->setEditable(false); } d->retranslateWindowTitle(); +#if defined(Q_WS_MAC) + d->deleteNativeDialog_sys(); + setAttribute(Qt::WA_DontShowOnScreen, false); +#endif } /* diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index db5c356..67daced 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -639,9 +639,16 @@ void QFileDialogPrivate::setFilter_sys() { #ifndef QT_MAC_USE_COCOA #else + Q_Q(QFileDialog); QMacCocoaAutoReleasePool pool; QNSOpenSavePanelDelegate *delegate = static_cast<QNSOpenSavePanelDelegate *>(mDelegate); *(delegate->mQDirFilter) = model->filter(); + delegate->mFileMode = fileMode; + [delegate->mSavePanel setTitle:qt_mac_QStringToNSString(q->windowTitle())]; + [delegate->mSavePanel setPrompt:[delegate strip:acceptLabel]]; + if (fileNameLabelExplicitlySat) + [delegate->mSavePanel setNameFieldLabel:[delegate strip:qFileDialogUi->fileNameLabel->text()]]; + [delegate updateProperties]; #endif } diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp index 42be780..6723b53 100644 --- a/src/gui/dialogs/qprintpreviewdialog.cpp +++ b/src/gui/dialogs/qprintpreviewdialog.cpp @@ -207,6 +207,9 @@ public: QActionGroup *printerGroup; QAction *printAction; QAction *pageSetupAction; +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + QAction *closeAction; +#endif QPointer<QObject> receiverToDisconnectOnClose; QByteArray memberToDisconnectOnClose; @@ -287,6 +290,9 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) toolbar->addSeparator(); toolbar->addAction(pageSetupAction); toolbar->addAction(printAction); +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + toolbar->addAction(closeAction); +#endif // Cannot use the actions' triggered signal here, since it doesn't autorepeat QToolButton *zoomInButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomInAction)); @@ -406,6 +412,10 @@ void QPrintPreviewDialogPrivate::setupActions() qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup")); QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print())); QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup())); +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close")); + QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject())); +#endif // Initial state: fitPageAction->setChecked(true); diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 90145fe..ad23df3 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -374,6 +374,11 @@ QGraphicsEffectSourcePrivate::~QGraphicsEffectSourcePrivate() invalidateCache(); } +void QGraphicsEffectSourcePrivate::setCachedOffset(const QPoint &offset) +{ + m_cachedOffset = offset; +} + void QGraphicsEffectSourcePrivate::invalidateCache(InvalidateReason reason) const { if (m_cachedMode != QGraphicsEffect::PadToEffectiveBoundingRect diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 91ad74a..e34dbf9 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -129,8 +129,10 @@ public: QGraphicsEffect::PixmapPadMode mode = QGraphicsEffect::PadToTransparentBorder) const = 0; virtual void effectBoundingRectChanged() = 0; + void setCachedOffset(const QPoint &offset); void invalidateCache(InvalidateReason reason = SourceChanged) const; Qt::CoordinateSystem currentCachedSystem() const { return m_cachedSystem; } + QGraphicsEffect::PixmapPadMode currentCachedMode() const { return m_cachedMode; } friend class QGraphicsScenePrivate; friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ebe04e3..c53a893 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -798,8 +798,36 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch return; } - foreach (QGraphicsItem *child, children) - child->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false); + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false); +} + +void QGraphicsItemPrivate::updateAncestorFlags() +{ + int flags = 0; + if (parent) { + // Inherit the parent's ancestor flags. + QGraphicsItemPrivate *pd = parent->d_ptr.data(); + flags = pd->ancestorFlags; + + // Add in flags from the parent. + if (pd->filtersDescendantEvents) + flags |= AncestorFiltersChildEvents; + if (pd->handlesChildEvents) + flags |= AncestorHandlesChildEvents; + if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape) + flags |= AncestorClipsChildren; + if (pd->flags & QGraphicsItem::ItemIgnoresTransformations) + flags |= AncestorIgnoresTransformations; + } + + if (ancestorFlags == flags) + return; // No change; stop propagation. + ancestorFlags = flags; + + // Propagate to children recursively. + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->updateAncestorFlags(); } /*! @@ -984,25 +1012,17 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query prepareGeometryChange) if the item is in its destructor, i.e. inDestructor is 1. */ -void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) +void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant, + const QVariant *thisPointerVariant) { Q_Q(QGraphicsItem); - if (newParent == q) { - qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); - return; - } - if (newParent == parent) - return; - - const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue<QGraphicsItem *>(newParent))); - newParent = qVariantValue<QGraphicsItem *>(newParentVariant); if (newParent == parent) return; if (scene) { // Deliver the change to the index - scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex) + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent); // Disable scene pos notifications for old ancestors if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) @@ -1020,11 +1040,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (!inDestructor) q_ptr->prepareGeometryChange(); - const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q)); if (parent) { // Remove from current parent parent->d_ptr->removeChild(q); - parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant); + if (thisPointerVariant) + parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant); } // Update toplevelitem list. If this item is being deleted, its parent @@ -1042,7 +1062,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *p = parent; QGraphicsItem *parentFocusScopeItem = 0; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { // If this item's focus scope's focus scope item points // to this item or a descendent, then clear it. QGraphicsItem *fsi = p->d_ptr->focusScopeItem; @@ -1055,6 +1075,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) p = p->d_ptr->parent; } + // Update graphics effect optimization flag + if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect)) + newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); + // Update focus scope item ptr in new scope. QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; if (newFocusScopeItem && newParent) { @@ -1063,11 +1087,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *ancestorScope = 0; QGraphicsItem *p = subFocusItem->d_ptr->parent; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) ancestorScope = p; - if (p->isPanel()) + if (p->d_ptr->flags & QGraphicsItem::ItemIsPanel) break; - p = p->parentItem(); + p = p->d_ptr->parent; } if (ancestorScope) newFocusScopeItem = ancestorScope; @@ -1075,7 +1099,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *p = newParent; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->focusScopeItem = newFocusScopeItem; // Ensure the new item is no longer the subFocusItem. The // only way to set focus on a child of a focus scope is @@ -1089,52 +1113,45 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } if ((parent = newParent)) { - bool implicitUpdate = false; if (parent->d_func()->scene && parent->d_func()->scene != scene) { // Move this item to its new parent's scene parent->d_func()->scene->addItem(q); - implicitUpdate = true; } else if (!parent->d_func()->scene && scene) { // Remove this item from its former scene scene->removeItem(q); } parent->d_ptr->addChild(q); - parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant); + if (thisPointerVariant) + parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant); if (scene) { - if (!implicitUpdate) - scene->d_func()->markDirty(q_ptr); - // Re-enable scene pos notifications for new ancestors if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) scene->d_func()->setScenePosItemEnabled(q, true); } + // Propagate dirty flags to the new parent + markParentDirty(/*updateBoundingRect=*/true); + // Inherit ancestor flags from the new parent. - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); - updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); - updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); + updateAncestorFlags(); // Update item visible / enabled. - if (parent->isVisible() != visible) { - if (!parent->isVisible() || !explicitlyHidden) - setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate); + if (parent->d_ptr->visible != visible) { + if (!parent->d_ptr->visible || !explicitlyHidden) + setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false); } if (parent->isEnabled() != enabled) { - if (!parent->isEnabled() || !explicitlyDisabled) - setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate); + if (!parent->d_ptr->enabled || !explicitlyDisabled) + setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false); } // Auto-activate if visible and the parent is active. - if (q->isVisible() && parent->isActive()) + if (visible && parent->isActive()) q->setActive(true); } else { // Inherit ancestor flags from the new parent. - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); - updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); - updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); + updateAncestorFlags(); if (!inDestructor) { // Update item visible / enabled. @@ -1142,10 +1159,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) setVisibleHelper(true, /* explicit = */ false); if (!enabled && !explicitlyDisabled) setEnabledHelper(true, /* explicit = */ false); - - // If the item is being deleted, the whole scene will be updated. - if (scene) - scene->d_func()->markDirty(q_ptr); } } @@ -1161,7 +1174,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Deliver post-change notification - q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + if (newParentVariant) + q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant); if (isObject) emit static_cast<QGraphicsObject *>(q)->parentChanged(); @@ -1351,7 +1365,7 @@ QGraphicsItem::~QGraphicsItem() d_ptr->scene->d_func()->removeItemHelper(this); } else { d_ptr->resetFocusProxy(); - d_ptr->setParentItemHelper(0); + setParentItem(0); } #ifndef QT_NO_GRAPHICSEFFECT @@ -1556,9 +1570,23 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const \sa parentItem(), childItems() */ -void QGraphicsItem::setParentItem(QGraphicsItem *parent) +void QGraphicsItem::setParentItem(QGraphicsItem *newParent) { - d_ptr->setParentItemHelper(parent); + if (newParent == this) { + qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); + return; + } + if (newParent == d_ptr->parent) + return; + + const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, + qVariantFromValue<QGraphicsItem *>(newParent))); + newParent = qVariantValue<QGraphicsItem *>(newParentVariant); + if (newParent == d_ptr->parent) + return; + + const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this)); + d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); } /*! @@ -1608,7 +1636,7 @@ bool QGraphicsItem::isWidget() const */ bool QGraphicsItem::isWindow() const { - return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window); + return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window); } /*! @@ -1645,9 +1673,9 @@ QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled) { if (enabled) - setFlags(flags() | flag); + setFlags(GraphicsItemFlags(d_ptr->flags) | flag); else - setFlags(flags() & ~flag); + setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag); } /*! @@ -1694,8 +1722,8 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); if (quint32(d_ptr->flags) == quint32(flags)) return; - if (d_ptr->scene) - d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); + if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) + d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags); // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); @@ -1704,7 +1732,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->paintedViewBoundingRectsNeedRepaint = 1; // Keep the old flags to compare the diff. - GraphicsItemFlags oldFlags = this->flags(); + GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags); // Update flags. d_ptr->flags = flags; @@ -1733,7 +1761,23 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->updateAncestorFlag(ItemIgnoresTransformations); } + if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { + // NB! We change the flags directly here, so we must also update d_ptr->flags. + // Note that this has do be done before the ItemStacksBehindParent check + // below; otherwise we will loose the change. + + // Update stack-behind. + if (d_ptr->z < qreal(0.0)) + flags |= ItemStacksBehindParent; + else + flags &= ~ItemStacksBehindParent; + d_ptr->flags = flags; + } + if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) { + // NB! This check has to come after the ItemNegativeZStacksBehindParent + // check above. Be careful. + // Ensure child item sorting is up to date when toggling this flag. if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; @@ -1747,10 +1791,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); } - if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { - // Update stack-behind. - setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0)); - } if ((d_ptr->panelModality != NonModal) && d_ptr->scene @@ -2524,7 +2564,9 @@ void QGraphicsItem::setOpacity(qreal opacity) // Update. if (d_ptr->scene) { #ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateGraphicsEffectsRecursively(); + d_ptr->invalidateParentGraphicsEffectsRecursively(); + if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren)) + d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged); #endif //QT_NO_GRAPHICSEFFECT d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -2569,6 +2611,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) if (d_ptr->graphicsEffect) { delete d_ptr->graphicsEffect; d_ptr->graphicsEffect = 0; + } else if (d_ptr->parent) { + d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); } if (effect) { @@ -2582,6 +2626,19 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) } #endif //QT_NO_GRAPHICSEFFECT +void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively() +{ +#ifndef QT_NO_GRAPHICSEFFECT + QGraphicsItemPrivate *itemPrivate = this; + do { + // parent chain already notified? + if (itemPrivate->mayHaveChildWithGraphicsEffect) + return; + itemPrivate->mayHaveChildWithGraphicsEffect = 1; + } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); +#endif +} + /*! \internal \since 4.6 @@ -2998,9 +3055,16 @@ void QGraphicsItem::setActive(bool active) */ bool QGraphicsItem::hasFocus() const { + if (!d_ptr->scene || !d_ptr->scene->isActive()) + return false; + if (d_ptr->focusProxy) return d_ptr->focusProxy->hasFocus(); - return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this); + + if (d_ptr->scene->d_func()->focusItem != this) + return false; + + return panel() == d_ptr->scene->d_func()->activePanel; } /*! @@ -4258,9 +4322,9 @@ void QGraphicsItem::setZValue(qreal z) if (newZ == d_ptr->z) return; - if (d_ptr->scene) { + if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) { // Z Value has changed, we have to notify the index. - d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); + d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ); } d_ptr->z = newZ; @@ -5027,7 +5091,7 @@ int QGraphicsItemPrivate::depth() const \internal */ #ifndef QT_NO_GRAPHICSEFFECT -void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() +void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively() { QGraphicsItemPrivate *itemPrivate = this; do { @@ -5039,6 +5103,24 @@ void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() } } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); } + +void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason) +{ + if (!mayHaveChildWithGraphicsEffect) + return; + + for (int i = 0; i < children.size(); ++i) { + QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data(); + if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; + if (childPrivate->graphicsEffect) { + childPrivate->notifyInvalidated = 1; + static_cast<QGraphicsItemEffectSourcePrivate *>(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); + } + + childPrivate->invalidateChildGraphicsEffectsRecursively(reason); + } +} #endif //QT_NO_GRAPHICSEFFECT /*! @@ -5283,7 +5365,7 @@ void QGraphicsItem::update(const QRectF &rect) // Make sure we notify effects about invalidated source. #ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateGraphicsEffectsRecursively(); + d_ptr->invalidateParentGraphicsEffectsRecursively(); #endif //QT_NO_GRAPHICSEFFECT if (CacheMode(d_ptr->cacheMode) != NoCache) { @@ -7176,19 +7258,7 @@ void QGraphicsItem::prepareGeometryChange() } } - QGraphicsItem *parent = this; - while ((parent = parent->d_ptr->parent)) { - QGraphicsItemPrivate *parentp = parent->d_ptr.data(); - parentp->dirtyChildrenBoundingRect = 1; - // ### Only do this if the parent's effect applies to the entire subtree. - parentp->notifyBoundingRectChanged = 1; -#ifndef QT_NO_GRAPHICSEFFECT - if (parentp->scene && parentp->graphicsEffect) { - parentp->notifyInvalidated = 1; - static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache(); - } -#endif - } + d_ptr->markParentDirty(/*updateBoundingRect=*/true); } /*! @@ -10716,27 +10786,18 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) } } -QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, - QGraphicsEffect::PixmapPadMode mode) const +QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const { - const bool deviceCoordinates = (system == Qt::DeviceCoordinates); - if (!info && deviceCoordinates) { - // Device coordinates without info not yet supported. - qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); - return QPixmap(); - } - if (!item->d_ptr->scene) - return QPixmap(); - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - - const QRectF sourceRect = boundingRect(system); QRectF effectRectF; - bool unpadded = false; + if (unpadded) + *unpadded = false; + if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { if (info) { effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates)); - unpadded = (effectRectF.size() == sourceRect.size()); + if (unpadded) + *unpadded = (effectRectF.size() == sourceRect.size()); if (info && system == Qt::LogicalCoordinates) effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF); } else { @@ -10748,10 +10809,29 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5); } else { effectRectF = sourceRect; - unpadded = true; + if (unpadded) + *unpadded = true; + } + + return effectRectF.toAlignedRect(); +} + +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffect::PixmapPadMode mode) const +{ + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + if (!info && deviceCoordinates) { + // Device coordinates without info not yet supported. + qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + return QPixmap(); } + if (!item->d_ptr->scene) + return QPixmap(); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - QRect effectRect = effectRectF.toAlignedRect(); + bool unpadded; + const QRectF sourceRect = boundingRect(system); + QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded); if (offset) *offset = effectRect.topLeft(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 7949a02..5ad6cd5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -153,7 +153,7 @@ public: dirtyChildren(0), localCollisionHack(0), inSetPosHelper(0), - needSortChildren(1), // ### can be 0 by default? + needSortChildren(0), allChildrenDirty(0), fullUpdatePending(0), flags(0), @@ -178,6 +178,8 @@ public: sequentialOrdering(1), updateDueToGraphicsEffect(0), scenePosDescendants(0), + pendingPolish(0), + mayHaveChildWithGraphicsEffect(0), globalStackingOrder(-1), q_ptr(0) { @@ -195,8 +197,10 @@ public: return item->d_ptr.data(); } + void updateChildWithGraphicsEffectFlagRecursively(); void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); + void updateAncestorFlags(); void setIsMemberOfGroup(bool enabled); void remapItemPos(QEvent *event, QGraphicsItem *item); QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; @@ -223,13 +227,18 @@ public: bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; int depth() const; #ifndef QT_NO_GRAPHICSEFFECT - void invalidateGraphicsEffectsRecursively(); + enum InvalidateReason { + OpacityChanged + }; + void invalidateParentGraphicsEffectsRecursively(); + void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason); #endif //QT_NO_GRAPHICSEFFECT void invalidateDepthRecursively(); void resolveDepth(); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); - void setParentItemHelper(QGraphicsItem *parent); + void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant, + const QVariant *thisPointerVariant); void childrenBoundingRectHelper(QTransform *x, QRectF *rect); void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems = false) const; @@ -397,6 +406,8 @@ public: return !visible || (childrenCombineOpacity() && isFullyTransparent()); } + inline void markParentDirty(bool updateBoundingRect = false); + void setFocusHelper(Qt::FocusReason focusReason, bool climb); void setSubFocus(QGraphicsItem *rootItem = 0); void clearSubFocus(QGraphicsItem *rootItem = 0); @@ -484,6 +495,8 @@ public: quint32 sequentialOrdering : 1; quint32 updateDueToGraphicsEffect : 1; quint32 scenePosDescendants : 1; + quint32 pendingPolish : 1; + quint32 mayHaveChildWithGraphicsEffect : 1; // Optional stacking order int globalStackingOrder; @@ -589,6 +602,7 @@ public: return item->type() == QGraphicsPixmapItem::Type && !(item->flags() & QGraphicsItem::ItemIsSelectable) && item->d_ptr->children.size() == 0; + //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func())); } inline const QStyleOption *styleOption() const @@ -608,6 +622,7 @@ public: QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset, QGraphicsEffect::PixmapPadMode mode) const; + QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; @@ -719,11 +734,13 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const inline void QGraphicsItemPrivate::ensureSortedChildren() { if (needSortChildren) { - qSort(children.begin(), children.end(), qt_notclosestLeaf); needSortChildren = 0; sequentialOrdering = 1; + if (children.isEmpty()) + return; + qSort(children.begin(), children.end(), qt_notclosestLeaf); for (int i = 0; i < children.size(); ++i) { - if (children[i]->d_ptr->siblingIndex != i) { + if (children.at(i)->d_ptr->siblingIndex != i) { sequentialOrdering = 0; break; } @@ -739,6 +756,37 @@ inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; } +/*! + \internal +*/ +inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect) +{ + QGraphicsItemPrivate *parentp = this; + while (parentp->parent) { + parentp = parentp->parent->d_ptr.data(); + parentp->dirtyChildren = 1; + + if (updateBoundingRect) { + parentp->dirtyChildrenBoundingRect = 1; + // ### Only do this if the parent's effect applies to the entire subtree. + parentp->notifyBoundingRectChanged = 1; + } +#ifndef QT_NO_GRAPHICSEFFECT + if (parentp->graphicsEffect) { + if (updateBoundingRect) { + parentp->notifyInvalidated = 1; + static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func() + ->source->d_func())->invalidateCache(); + } + if (parentp->graphicsEffect->isEnabled()) { + parentp->dirty = 1; + parentp->fullUpdatePending = 1; + } + } +#endif + } +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5c6a8ae..9219773 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -292,7 +292,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() processDirtyItemsEmitted(false), selectionChanging(0), needSortTopLevelItems(true), - unpolishedItemsModified(true), holesInTopLevelSiblingIndex(false), topLevelSequentialOrdering(true), scenePosDescendantsUpdatePending(false), @@ -429,22 +428,38 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::_q_polishItems() { - QSet<QGraphicsItem *>::Iterator it = unpolishedItems.begin(); + if (unpolishedItems.isEmpty()) + return; + const QVariant booleanTrueVariant(true); - while (!unpolishedItems.isEmpty()) { - QGraphicsItem *item = *it; - it = unpolishedItems.erase(it); - unpolishedItemsModified = false; - if (!item->d_ptr->explicitlyHidden) { + QGraphicsItem *item = 0; + QGraphicsItemPrivate *itemd = 0; + const int oldUnpolishedCount = unpolishedItems.count(); + + for (int i = 0; i < oldUnpolishedCount; ++i) { + item = unpolishedItems.at(i); + if (!item) + continue; + itemd = item->d_ptr.data(); + itemd->pendingPolish = false; + if (!itemd->explicitlyHidden) { item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); } - if (item->isWidget()) { + if (itemd->isWidget) { QEvent event(QEvent::Polish); QApplication::sendEvent((QGraphicsWidget *)item, &event); } - if (unpolishedItemsModified) - it = unpolishedItems.begin(); + } + + if (unpolishedItems.count() == oldUnpolishedCount) { + // No new items were added to the vector. + unpolishedItems.clear(); + } else { + // New items were appended; keep them and remove the old ones. + unpolishedItems.remove(0, oldUnpolishedCount); + unpolishedItems.squeeze(); + QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection); } } @@ -599,7 +614,7 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) if (parentItem->scene()) { Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem", "Parent item's scene is different from this item's scene"); - item->d_ptr->setParentItemHelper(0); + item->setParentItem(0); } } else { unregisterTopLevelItem(item); @@ -638,8 +653,12 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) selectedItems.remove(item); hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); - unpolishedItems.remove(item); - unpolishedItemsModified = true; + if (item->d_ptr->pendingPolish) { + const int unpolishedIndex = unpolishedItems.indexOf(item); + if (unpolishedIndex != -1) + unpolishedItems[unpolishedIndex] = 0; + item->d_ptr->pendingPolish = false; + } resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays @@ -1936,7 +1955,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe \since 4.3 This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). - + This function is deprecated and returns incorrect results if the scene contains items that ignore transformations. Use the overload that takes a QTransform instead. @@ -2482,12 +2501,12 @@ void QGraphicsScene::addItem(QGraphicsItem *item) qWarning("QGraphicsScene::addItem: cannot add null item"); return; } - if (item->scene() == this) { + if (item->d_ptr->scene == this) { qWarning("QGraphicsScene::addItem: item has already been added to this scene"); return; } // Remove this item from its existing scene - if (QGraphicsScene *oldScene = item->scene()) + if (QGraphicsScene *oldScene = item->d_ptr->scene) oldScene->removeItem(item); // Notify the item that its scene is changing, and allow the item to @@ -2496,15 +2515,20 @@ void QGraphicsScene::addItem(QGraphicsItem *item) qVariantFromValue<QGraphicsScene *>(this))); QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); if (targetScene != this) { - if (targetScene && item->scene() != targetScene) + if (targetScene && item->d_ptr->scene != targetScene) targetScene->addItem(item); return; } + if (d->unpolishedItems.isEmpty()) + QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); + d->unpolishedItems.append(item); + item->d_ptr->pendingPolish = true; + // Detach this item from its parent if the parent's scene is different // from this scene. - if (QGraphicsItem *itemParent = item->parentItem()) { - if (itemParent->scene() != this) + if (QGraphicsItem *itemParent = item->d_ptr->parent) { + if (itemParent->d_ptr->scene != this) item->setParentItem(0); } @@ -2534,7 +2558,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) d->enableMouseTrackingOnViews(); } #ifndef QT_NO_CURSOR - if (d->allItemsUseDefaultCursor && item->hasCursor()) { + if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) { d->allItemsUseDefaultCursor = false; if (d->allItemsIgnoreHoverEvents) // already enabled otherwise d->enableMouseTrackingOnViews(); @@ -2542,7 +2566,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) #endif //QT_NO_CURSOR // Enable touch events if the item accepts touch events. - if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) { + if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) { d->allItemsIgnoreTouchEvents = false; d->enableTouchEventsOnViews(); } @@ -2575,17 +2599,14 @@ void QGraphicsScene::addItem(QGraphicsItem *item) } // Add all children recursively - foreach (QGraphicsItem *child, item->children()) - addItem(child); + item->d_ptr->ensureSortedChildren(); + for (int i = 0; i < item->d_ptr->children.size(); ++i) + addItem(item->d_ptr->children.at(i)); // Resolve font and palette. item->d_ptr->resolveFont(d->font.resolve()); item->d_ptr->resolvePalette(d->palette.resolve()); - if (d->unpolishedItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); - d->unpolishedItems.insert(item); - d->unpolishedItemsModified = true; // Reenable selectionChanged() for individual items --d->selectionChanging; @@ -2619,7 +2640,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) } } - if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) + if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges) d->registerScenePosItem(item); // Ensure that newly added items that have subfocus set, gain @@ -3766,10 +3787,10 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const { - return (!item->isBlockedByModalPanel() && - (item->acceptHoverEvents() - || (item->isWidget() - && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))); + return (item->d_ptr->acceptsHover + || (item->d_ptr->isWidget + && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())) + && !item->isBlockedByModalPanel(); } /*! @@ -4686,8 +4707,31 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (sourced->currentCachedSystem() != Qt::LogicalCoordinates && sourced->lastEffectTransform != painter->worldTransform()) { + bool unclipped = false; + if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate + && painter->worldTransform().type() <= QTransform::TxTranslate) + { + QRectF itemRect = item->boundingRect(); + if (!item->d_ptr->children.isEmpty()) + itemRect |= item->childrenBoundingRect(); + + QRectF oldSourceRect = sourced->lastEffectTransform.mapRect(itemRect); + QRectF newSourceRect = painter->worldTransform().mapRect(itemRect); + + QRect oldEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), oldSourceRect); + QRect newEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), newSourceRect); + + QRect deviceRect(0, 0, painter->device()->width(), painter->device()->height()); + if (deviceRect.contains(oldEffectRect) && deviceRect.contains(newEffectRect)) { + sourced->setCachedOffset(newEffectRect.topLeft()); + unclipped = true; + } + } + sourced->lastEffectTransform = painter->worldTransform(); - sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); + + if (!unclipped) + sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); } item->d_ptr->graphicsEffect->draw(painter); @@ -4859,17 +4903,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (ignoreOpacity) item->d_ptr->ignoreOpacity = 1; - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - p->d_ptr->dirtyChildren = 1; -#ifndef QT_NO_GRAPHICSEFFECT - if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { - p->d_ptr->dirty = 1; - p->d_ptr->fullUpdatePending = 1; - } -#endif //QT_NO_GRAPHICSEFFECT - p = p->d_ptr->parent; - } + item->d_ptr->markParentDirty(); } static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index d10811c..54d8130 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -108,10 +108,9 @@ public: QPainterPath selectionArea; int selectionChanging; QSet<QGraphicsItem *> selectedItems; - QSet<QGraphicsItem *> unpolishedItems; + QVector<QGraphicsItem *> unpolishedItems; QList<QGraphicsItem *> topLevelItems; bool needSortTopLevelItems; - bool unpolishedItemsModified; bool holesInTopLevelSiblingIndex; bool topLevelSequentialOrdering; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 2e92b87..2a91348 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -635,16 +635,17 @@ void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) This method react to the \a change of the \a item and use the \a value to update the BSP tree if necessary. */ -void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) { Q_D(QGraphicsSceneBspTreeIndex); switch (change) { case QGraphicsItem::ItemFlagsChange: { // Handle ItemIgnoresTransformations + QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value); bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations; - bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; + bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations; bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; - bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape; + bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape; if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) { QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item); // Remove item and its descendants from the index and append @@ -661,7 +662,7 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics case QGraphicsItem::ItemParentChange: { d->invalidateSortCache(); // Handle ItemIgnoresTransformations - QGraphicsItem *newParent = qVariantValue<QGraphicsItem *>(value); + const QGraphicsItem *newParent = static_cast<const QGraphicsItem *>(value); bool ignoredTransform = item->d_ptr->itemIsUntransformable(); bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); @@ -682,7 +683,6 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics default: break; } - return QGraphicsSceneIndex::itemChange(item, change, value); } /*! \reimp diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 119571b..f671fd9 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -97,7 +97,7 @@ protected: void removeItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value); private : Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index bc8a7dc..043c4eb 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -624,7 +624,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa QGraphicsItem::GraphicsItemChange */ -void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) { Q_UNUSED(item); Q_UNUSED(change); diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index def58f0..597a229 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -110,7 +110,7 @@ protected: virtual void removeItem(QGraphicsItem *item) = 0; virtual void deleteItem(QGraphicsItem *item); - virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const void *const value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene); diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 854be2e..42e19b8 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -144,7 +144,7 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi) static int calc_shift(int mask) { int result = 0; - while (!(mask & 1)) { + while (mask && !(mask & 1)) { result++; mask >>= 1; } diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 4e10b5b..4f5efa1 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3992,7 +3992,7 @@ QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Transf QSize newSize = size(); newSize.scale(s, aspectMode); if (newSize == size()) - return copy(); + return *this; QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height()); QImage img = transformed(wm, mode); diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 674d5da..f823fdc 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -833,14 +833,21 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers if (QPixmapCache::find(key, *this)) return true; - QPixmapData *tmp = QPixmapData::create(0, 0, QPixmapData::PixmapType); - if (tmp->fromFile(fileName, format, flags)) { - data = tmp; - QPixmapCache::insert(key, *this); - return true; + bool ok; + + if (data) { + ok = data->fromFile(fileName, format, flags); + } else { + QScopedPointer<QPixmapData> tmp(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + ok = tmp->fromFile(fileName, format, flags); + if (ok) + data = tmp.take(); } - delete tmp; - return false; + + if (ok) + QPixmapCache::insert(key, *this); + + return ok; } /*! diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 30fb7a3..37a6a18 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -953,7 +953,7 @@ static void grayscale(const QImage &image, QImage &dest, const QRect& rect = QRe srcRect = dest.rect(); destRect = dest.rect(); } - if (image != dest) { + if (&image != &dest) { destRect.moveTo(QPoint(0, 0)); } diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 0b84e2f..f5034fc 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -57,6 +57,7 @@ #include "qinputcontext.h" #include <qhash.h> +#include <qtimer.h> #include <private/qcore_symbian_p.h> #include <private/qt_s60_p.h> @@ -91,6 +92,9 @@ public: TCoeInputCapabilities inputCapabilities(); +protected: + void timerEvent(QTimerEvent *timerEvent); + private: void commitCurrentString(bool triggeredBySymbian); void updateHints(bool mustUpdateInputCapabilities); @@ -98,6 +102,7 @@ private: void applyFormat(QList<QInputMethodEvent::Attribute> *attributes); void queueInputCapabilitiesChanged(); bool needsInputPanel(); + void commitTemporaryPreeditString(); private Q_SLOTS: void ensureInputCapabilitiesChanged(); @@ -148,6 +153,8 @@ private: MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; int m_longPress; int m_cursorPos; + QBasicTimer m_tempPreeditStringTimeout; + bool m_hasTempPreeditString; }; QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index d2f207a..793bcde 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -72,7 +72,8 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_formatRetriever(0), m_pointerHandler(0), m_longPress(0), - m_cursorPos(0) + m_cursorPos(0), + m_hasTempPreeditString(false) { m_fepState->SetObjectProvider(this); m_fepState->SetFlags(EAknEditorFlagDefault); @@ -100,6 +101,8 @@ QCoeFepInputContext::~QCoeFepInputContext() void QCoeFepInputContext::reset() { + commitTemporaryPreeditString(); + CCoeFep* fep = CCoeEnv::Static()->Fep(); if (fep) fep->CancelTransaction(); @@ -200,7 +203,11 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) if (!focusWidget()) return false; - if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + switch (event->type()) { + case QEvent::KeyPress: + commitTemporaryPreeditString(); + // fall through intended + case QEvent::KeyRelease: const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); switch (keyEvent->key()) { case Qt::Key_F20: @@ -223,6 +230,21 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) default: break; } + + if (keyEvent->type() == QEvent::KeyPress + && focusWidget()->inputMethodHints() & Qt::ImhHiddenText + && !keyEvent->text().isEmpty()) { + // Send some temporary preedit text in order to make text visible for a moment. + m_preeditString = keyEvent->text(); + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent imEvent(m_preeditString, attributes); + QApplication::sendEvent(focusWidget(), &imEvent); + m_tempPreeditStringTimeout.start(1000, this); + m_hasTempPreeditString = true; + update(); + return true; + } + break; } if (!needsInputPanel()) @@ -253,6 +275,24 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) return false; } +void QCoeFepInputContext::timerEvent(QTimerEvent *timerEvent) +{ + if (timerEvent->timerId() == m_tempPreeditStringTimeout.timerId()) + commitTemporaryPreeditString(); +} + +void QCoeFepInputContext::commitTemporaryPreeditString() +{ + if (m_tempPreeditStringTimeout.isActive()) + m_tempPreeditStringTimeout.stop(); + + if (!m_hasTempPreeditString) + return; + + commitCurrentString(false); + m_hasTempPreeditString = false; +} + void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) { Q_ASSERT(focusWidget()); @@ -310,6 +350,8 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) { using namespace Qt; + commitTemporaryPreeditString(); + bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly || hints & ImhDialableCharactersOnly; bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly @@ -501,6 +543,8 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, if (!w) return; + commitTemporaryPreeditString(); + m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); QList<QInputMethodEvent::Attribute> attributes; @@ -600,6 +644,8 @@ void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCur if (!w) return; + commitTemporaryPreeditString(); + int pos = aCursorSelection.iAnchorPos; int length = aCursorSelection.iCursorPos - pos; diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index f289c7d..19b1e8c 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -2621,6 +2621,13 @@ bool QIconModeViewBase::filterDropEvent(QDropEvent *e) const QSize contents = contentsSize; QPoint offset(horizontalOffset(), verticalOffset()); QPoint end = e->pos() + offset; + if (qq->acceptDrops()) { + const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled; + const QVector<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1))); + foreach (const QModelIndex &index, dropIndices) + if ((index.flags() & dropableFlags) == dropableFlags) + return false; + } QPoint start = dd->pressedPosition; QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start); QList<QModelIndex> indexes = dd->selectionModel->selectedIndexes(); diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 7eefb0b..3111896 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -114,7 +114,9 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height) } } else if (old_height > span->height()) { //remove the span from all the subspans lists that intersect the columns not covered anymore - Index::iterator it_y = index.lowerBound(qMin(-span->bottom(), 0)); + Index::iterator it_y = index.lowerBound(-span->bottom()); + if (it_y == index.end()) + it_y = index.find(-span->top()); // This is the only span remaining and we are deleting it. Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list while (-it_y.key() <= span->top() + old_height -1) { if (-it_y.key() > span->bottom()) { diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 12fe797..4fe3900 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -121,8 +121,10 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp static void initResources() { -#ifdef Q_WS_WINCE +#if defined(Q_WS_WINCE) Q_INIT_RESOURCE(qstyle_wince); +#elif defined(Q_OS_SYMBIAN) + Q_INIT_RESOURCE(qstyle_s60); #else Q_INIT_RESOURCE(qstyle); #endif diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 6aebef5..e8b821af 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -227,8 +227,29 @@ void onApplicationChangedActivation( bool activated ); static void qt_mac_read_fontsmoothing_settings() { - NSInteger appleFontSmoothing = [[NSUserDefaults standardUserDefaults] integerForKey:@"AppleFontSmoothing"]; - qt_applefontsmoothing_enabled = (appleFontSmoothing > 0); + qt_applefontsmoothing_enabled = true; + int w = 10, h = 10; + QImage image(w, h, QImage::Format_RGB32); + image.fill(0xffffffff); + QPainter p(&image); + p.drawText(0, h, "X\\"); + p.end(); + + const int *bits = (const int *) ((const QImage &) image).bits(); + int bpl = image.bytesPerLine() / 4; + for (int y=0; y<w; ++y) { + for (int x=0; x<h; ++x) { + int r = qRed(bits[x]); + int g = qGreen(bits[x]); + int b = qBlue(bits[x]); + if (r != g || r != b) { + qt_applefontsmoothing_enabled = true; + return; + } + } + bits += bpl; + } + qt_applefontsmoothing_enabled = false; } Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) { @@ -772,11 +793,11 @@ static void qt_mac_update_intersected_gl_widgets(QWidget *widget) qt_post_window_change_event(glWidget); it->lastUpdateWidget = widget; } else if (it->lastUpdateWidget == widget) { - // Update the gl wigets that the widget intersected the last time around, - // and that we are not intersecting now. This prevents paint errors when the + // Update the gl wigets that the widget intersected the last time around, + // and that we are not intersecting now. This prevents paint errors when the // intersecting widget leaves a gl widget. qt_post_window_change_event(glWidget); - it->lastUpdateWidget = 0; + it->lastUpdateWidget = 0; } } #else @@ -808,8 +829,8 @@ Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget) // Post a kEventQtRequestWindowChange event. This event is semi-public, // don't remove this line! qt_event_request_window_change(); - - // Post update request on gl widgets unconditionally. + + // Post update request on gl widgets unconditionally. if (qt_widget_private(widget)->isGLWidget == true) { qt_post_window_change_event(widget); return; @@ -1214,8 +1235,6 @@ void qt_init(QApplicationPrivate *priv, int) if (QApplication::desktopSettingsAware()) QApplicationPrivate::qt_mac_apply_settings(); - qt_mac_read_fontsmoothing_settings(); - // Cocoa application delegate #ifdef QT_MAC_USE_COCOA NSApplication *cocoaApp = [NSApplication sharedApplication]; @@ -1253,6 +1272,7 @@ void qt_init(QApplicationPrivate *priv, int) } priv->native_modal_dialog_active = false; + qt_mac_read_fontsmoothing_settings(); } void qt_release_apple_event_handler() @@ -1705,7 +1725,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event // kEventMouseWheelMoved events if we dont eat this event // (actually two events; one for horizontal and one for vertical). // As a results of this, and to make sure we dont't receive duplicate events, - // we try to detect when this happend by checking the 'compatibilityEvent'. + // we try to detect when this happend by checking the 'compatibilityEvent'. SInt32 mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); @@ -2576,7 +2596,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup delete QApplicationPrivate::popupWidgets; QApplicationPrivate::popupWidgets = 0; - + // Special case for Tool windows: since they are activated and deactived together // with a normal window they never become the QApplicationPrivate::active_window. QWidget *appFocusWidget = QApplication::focusWidget(); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index f8943a8..9c001ab 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -501,9 +501,9 @@ public: static TUint resolveS60ScanCode(TInt scanCode, TUint keysym); QSet<WId> nativeWindows; - int symbianProcessWsEvent(const TWsEvent *event); - int symbianHandleCommand(int command); - int symbianResourceChange(int type); + int symbianProcessWsEvent(const QSymbianEvent *symbianEvent); + int symbianHandleCommand(const QSymbianEvent *symbianEvent); + int symbianResourceChange(const QSymbianEvent *symbianEvent); #endif #if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 3ee0a71..6caac9f 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -71,6 +71,7 @@ # include <private/qcoefepinputcontext_p.h> # endif # include <private/qs60mainapplication_p.h> +# include <centralrepository.h> #endif #include "private/qstylesheetstyle_p.h" @@ -807,6 +808,15 @@ TCoeInputCapabilities QSymbianControl::InputCapabilities() const void QSymbianControl::Draw(const TRect& controlRect) const { + // Set flag to avoid calling DrawNow in window surface + QWExtra *extra = qwidget->d_func()->extraData(); + if (extra && !extra->inExpose) { + extra->inExpose = true; + QRect exposeRect = qt_TRect2QRect(controlRect); + qwidget->d_func()->syncBackingStore(exposeRect); + extra->inExpose = false; + } + QWindowSurface *surface = qwidget->windowSurface(); QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL; @@ -855,8 +865,6 @@ void QSymbianControl::Draw(const TRect& controlRect) const default: Q_ASSERT(false); } - } else { - surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint()); } if (sendNativePaintEvents) { @@ -1197,6 +1205,24 @@ void qt_init(QApplicationPrivate * /* priv */, int) S60->virtualMouseRequired = false; } + S60->avkonComponentsSupportTransparency = false; + +#ifdef Q_WS_S60 + TUid KCRUidAvkon = { 0x101F876E }; + TUint32 KAknAvkonTransparencyEnabled = 0x0000000D; + + CRepository* repository = 0; + TRAP(err, repository = CRepository::NewL(KCRUidAvkon)); + + if(err == KErrNone) { + TInt value = 0; + err = repository->Get(KAknAvkonTransparencyEnabled, value); + if(err == KErrNone) { + S60->avkonComponentsSupportTransparency = (value==1) ? true : false; + } + } +#endif + if (touch) { QApplicationPrivate::navigationMode = Qt::NavigationModeNone; } else { @@ -1521,6 +1547,12 @@ void QApplication::beep() qt_S60Beep->Play(); } +static inline bool callSymbianEventFilters(const QSymbianEvent *event) +{ + long unused; + return qApp->filterEvent(const_cast<QSymbianEvent *>(event), &unused); +} + /*! \warning This function is only available on Symbian. \since 4.6 @@ -1537,6 +1569,9 @@ int QApplication::symbianProcessEvent(const QSymbianEvent *event) QScopedLoopLevelCounter counter(d->threadData); + if (d->eventDispatcher->filterEvent(const_cast<QSymbianEvent *>(event))) + return 1; + QWidget *w = qApp ? qApp->focusWidget() : 0; if (w) { QInputContext *ic = w->inputContext(); @@ -1549,29 +1584,34 @@ int QApplication::symbianProcessEvent(const QSymbianEvent *event) switch (event->type()) { case QSymbianEvent::WindowServerEvent: - return d->symbianProcessWsEvent(event->windowServerEvent()); + return d->symbianProcessWsEvent(event); case QSymbianEvent::CommandEvent: - return d->symbianHandleCommand(event->command()); + return d->symbianHandleCommand(event); case QSymbianEvent::ResourceChangeEvent: - return d->symbianResourceChange(event->resourceChangeType()); + return d->symbianResourceChange(event); default: return -1; } } -int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event) +int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent) { // Qt event handling. Handle some events regardless of if the handle is in our // widget map or not. + const TWsEvent *event = symbianEvent->windowServerEvent(); CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle()); const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control); switch (event->Type()) { case EEventPointerEnter: - if (controlInMap) + if (controlInMap) { + callSymbianEventFilters(symbianEvent); return 1; // Qt::Enter will be generated in HandlePointerL + } break; case EEventPointerExit: if (controlInMap) { + if (callSymbianEventFilters(symbianEvent)) + return 1; if (S60) { // mouseEvent outside our window, send leave event to last focused widget QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos, @@ -1584,6 +1624,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event) } break; case EEventScreenDeviceChanged: + if (callSymbianEventFilters(symbianEvent)) + return 1; if (S60) S60->updateScreenSize(); if (qt_desktopWidget) { @@ -1596,6 +1638,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event) return 0; // Propagate to CONE case EEventWindowVisibilityChanged: if (controlInMap) { + if (callSymbianEventFilters(symbianEvent)) + return 1; const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged(); QWidget *w = QWidgetPrivate::mapper->value(control); if (!w->d_func()->maybeTopData()) @@ -1613,6 +1657,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event) } break; case EEventFocusGained: + if (callSymbianEventFilters(symbianEvent)) + return 1; #ifndef QT_NO_CURSOR //re-enable mouse interaction if (S60->mouseInteractionEnabled) { @@ -1626,6 +1672,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event) #endif break; case EEventFocusLost: + if (callSymbianEventFilters(symbianEvent)) + return 1; #ifndef QT_NO_CURSOR //disable mouse as may be moving to application that does not support it if (S60->mouseInteractionEnabled) { @@ -1677,11 +1725,16 @@ bool QApplication::symbianEventFilter(const QSymbianEvent *event) \sa s60EventFilter(), s60ProcessEvent() */ -int QApplicationPrivate::symbianHandleCommand(int command) +int QApplicationPrivate::symbianHandleCommand(const QSymbianEvent *symbianEvent) { Q_Q(QApplication); int ret = 0; + if (callSymbianEventFilters(symbianEvent)) + return 1; + + int command = symbianEvent->command(); + switch (command) { #ifdef Q_WS_S60 case EAknSoftkeyExit: { @@ -1721,14 +1774,18 @@ int QApplicationPrivate::symbianHandleCommand(int command) Currently, KEikDynamicLayoutVariantSwitch and KAknsMessageSkinChange are handled. */ -int QApplicationPrivate::symbianResourceChange(int type) +int QApplicationPrivate::symbianResourceChange(const QSymbianEvent *symbianEvent) { int ret = 0; + int type = symbianEvent->resourceChangeType(); + switch (type) { #ifdef Q_WS_S60 case KEikDynamicLayoutVariantSwitch: { + if (callSymbianEventFilters(symbianEvent)) + return 1; if (S60) S60->updateScreenSize(); @@ -1753,6 +1810,8 @@ int QApplicationPrivate::symbianResourceChange(int type) #ifndef QT_NO_STYLE_S60 case KAknsMessageSkinChange: + if (callSymbianEventFilters(symbianEvent)) + return 1; if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style())) { s60Style->d_func()->handleSkinChange(); ret = 1; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index c14798a..f61d2fe 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -510,7 +510,7 @@ extern "C" { } // Make sure the opengl context is updated on resize. - if (0 && qwidgetprivate->isGLWidget) { + if (qwidgetprivate->isGLWidget) { qwidgetprivate->needWindowChange = true; QEvent event(QEvent::MacGLWindowChange); qApp->sendEvent(qwidget, &event); diff --git a/src/gui/kernel/qdesktopwidget.cpp b/src/gui/kernel/qdesktopwidget.cpp index c8a4373..24b4e57 100644 --- a/src/gui/kernel/qdesktopwidget.cpp +++ b/src/gui/kernel/qdesktopwidget.cpp @@ -47,6 +47,11 @@ QT_BEGIN_NAMESPACE const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const { + if (!widget) { + qWarning("QDesktopWidget::screenGeometry(): Attempt " + "to get the screen geometry of a null widget"); + return QRect(); + } QRect rect = QWidgetPrivate::screenGeometry(widget); if (rect.isNull()) return screenGeometry(screenNumber(widget)); @@ -55,6 +60,11 @@ const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const { + if (!widget) { + qWarning("QDesktopWidget::availableGeometry(): Attempt " + "to get the available geometry of a null widget"); + return QRect(); + } QRect rect = QWidgetPrivate::screenGeometry(widget); if (rect.isNull()) return availableGeometry(screenNumber(widget)); diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index b44cd50..aebc3a5 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -1925,11 +1925,11 @@ void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, Q /* If the field on the right-hand side is tall, we want the label to be top-aligned, but not too - much. So we introduce a 5 / 4 factor so that it - gets a few extra pixels at the top. + much. So we introduce a 7 / 4 factor so that it + gets some extra pixels at the top. */ height = qMin(height, - qMin(label->sizeHint.height() * 5 / 4, + qMin(label->sizeHint.height() * 7 / 4, label->maxSize.height())); } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index b417065..1163055 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -121,6 +121,7 @@ public: int virtualMouseRequired : 1; int qtOwnsS60Environment : 1; int supportsPremultipliedAlpha : 1; + int avkonComponentsSupportTransparency : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static inline void updateScreenSize(); static inline RWsSession& wsSession(); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 81a9a80..ede87de 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -2026,6 +2026,14 @@ void QWidgetPrivate::updateIsOpaque() } #endif +#ifdef Q_WS_S60 + if (q->windowType() == Qt::Dialog && q->testAttribute(Qt::WA_TranslucentBackground) + && S60->avkonComponentsSupportTransparency) { + setOpaque(false); + return; + } +#endif + if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) { setOpaque(true); return; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 354a666..3dbc843 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -110,6 +110,7 @@ #include "qevent_p.h" #include "qdnd_p.h" #include <QtGui/qgraphicsproxywidget.h> +#include "qmainwindow.h" QT_BEGIN_NAMESPACE @@ -1721,6 +1722,15 @@ bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, void QWidgetPrivate::determineWindowClass() { Q_Q(QWidget); +#if !defined(QT_NO_MAINWINDOW) && !defined(QT_NO_TOOLBAR) + // Make sure that QMainWindow has the MacWindowToolBarButtonHint when the + // unifiedTitleAndToolBarOnMac property is ON. This is to avoid reentry of + // setParent() triggered by the QToolBar::event(QEvent::ParentChange). + QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q); + if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { + data.window_flags |= Qt::MacWindowToolBarButtonHint; + } +#endif #ifndef QT_MAC_USE_COCOA // ### COCOA:Interleave these better! @@ -2743,7 +2753,9 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) } if (wasWindow) { oldToolbar = [oldWindow toolbar]; + [oldToolbar retain]; oldToolbarVisible = [oldToolbar isVisible]; + [oldWindow setToolbar:nil]; } #endif } @@ -2787,6 +2799,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) if (oldToolbar && !(f & Qt::FramelessWindowHint)) { OSWindowRef newWindow = qt_mac_window_for(q); [newWindow setToolbar:oldToolbar]; + [oldToolbar release]; [oldToolbar setVisible:oldToolbarVisible]; } #endif @@ -3401,6 +3414,38 @@ void QWidgetPrivate::hide_sys() ShowHide(window, false); #else [window orderOut:window]; + // Unfortunately it is not as easy as just hiding the window, we need + // to find out if we were in full screen mode. If we were and this is + // the last window in full screen mode then we need to unset the full screen + // mode. If this is not the last visible window in full screen mode then we + // don't change the full screen mode. + if(q->isFullScreen()) + { + bool keepFullScreen = false; + QWidgetList windowList = qApp->topLevelWidgets(); + int windowCount = windowList.count(); + for(int i = 0; i < windowCount; i++) + { + QWidget *w = windowList[i]; + // If it is the same window, we don't need to check :-) + if(q == w) + continue; + // If they are not visible or if they are minimized then + // we just ignore them. + if(!w->isVisible() || w->isMinimized()) + continue; + // Is it full screen? + // Notice that if there is one window in full screen mode then we + // cannot switch the full screen mode off, therefore we just abort. + if(w->isFullScreen()) { + keepFullScreen = true; + break; + } + } + // No windows in full screen mode, so let just unset that flag. + if(!keepFullScreen) + qt_mac_set_fullscreen_mode(false); + } #endif toggleDrawers(false); #ifndef QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index ec8d20f..b1eb3c3 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -229,6 +229,7 @@ struct QWExtra { #endif #elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian uint activated : 1; // RWindowBase::Activated has been called + uint inExpose : 1; // Prevents drawing recursion /** * Defines the behaviour of QSymbianControl::Draw. diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index c65a162..00f2213 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -389,9 +389,13 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de if (!isOpaque) { RWindow *const window = static_cast<RWindow *>(drawableWindow); +#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE + window->SetSurfaceTransparency(true); +#else const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); if (window->SetTransparencyAlphaChannel() == KErrNone) window->SetBackgroundColor(TRgb(255, 255, 255, 0)); +#endif } } @@ -707,12 +711,16 @@ void QWidgetPrivate::s60UpdateIsOpaque() RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); +#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE + window->SetSurfaceTransparency(!isOpaque); +#else if (!isOpaque) { const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); if (window->SetTransparencyAlphaChannel() == KErrNone) window->SetBackgroundColor(TRgb(255, 255, 255, 0)); } else window->SetTransparentRegion(TRegionFix<1>()); +#endif } void QWidgetPrivate::setWindowIcon_sys(bool forceReset) @@ -883,6 +891,7 @@ void QWidgetPrivate::createSysExtra() extra->activated = 0; extra->nativePaintMode = QWExtra::Default; extra->receiveNativePaintEvents = 0; + extra->inExpose = 0; } void QWidgetPrivate::deleteSysExtra() diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index f51dc36..d6d288e 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -934,8 +934,7 @@ void QColor::setRgb(int r, int g, int b, int a) /*! \fn QRgb QColor::rgba() const - Returns the RGB value of the color. Unlike rgb(), the alpha is not - stripped. + Returns the RGB value of the color, including its alpha. For an invalid color, the alpha value of the returned color is unspecified. @@ -950,8 +949,7 @@ QRgb QColor::rgba() const } /*! - Sets the RGBA value to \a rgba. Unlike setRgb(QRgb rgb), this function does - not ignore the alpha. + Sets the RGB value to \a rgba, including its alpha. \sa rgba(), rgb() */ @@ -968,8 +966,7 @@ void QColor::setRgba(QRgb rgba) /*! \fn QRgb QColor::rgb() const - Returns the RGB value of the color. The alpha is stripped for - compatibility. + Returns the RGB value of the color. The alpha value is opaque. \sa getRgb(), rgba() */ @@ -983,7 +980,7 @@ QRgb QColor::rgb() const /*! \overload - Sets the RGB value to \a rgb, ignoring the alpha. + Sets the RGB value to \a rgb. The alpha value is set to opaque. */ void QColor::setRgb(QRgb rgb) { diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index b937f66..a1c73cc 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -264,13 +264,13 @@ private: #endif // Q_OS_SYMBIAN && QT_NO_FREETYPE inline void ensureBrush(const QBrush &brush) { - if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags) + if (!qbrush_fast_equals(state()->lastBrush, brush) || (brush.style() != Qt::NoBrush && state()->fillFlags)) updateBrush(brush); } inline void ensureBrush() { ensureBrush(state()->brush); } inline void ensurePen(const QPen &pen) { - if (!qpen_fast_equals(state()->lastPen, pen) || state()->strokeFlags) + if (!qpen_fast_equals(state()->lastPen, pen) || (pen.style() != Qt::NoPen && state()->strokeFlags)) updatePen(pen); } inline void ensurePen() { ensurePen(state()->pen); } diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 058f226..4f2fffa 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -417,13 +417,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) } else if (style == Qt::NoPen) { d->activeStroker = 0; } else { - // ### re-enable... - if (pen.isCosmetic()) { - d->dasher.setClipRect(d->exDeviceRect); - } else { - QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); - d->dasher.setClipRect(clipRect); - } d->dasher.setDashPattern(pen.dashPattern()); d->dasher.setDashOffset(pen.dashOffset()); d->activeStroker = &d->dasher; @@ -434,6 +427,15 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) return; } + if (pen.style() > Qt::SolidLine) { + if (pen.isCosmetic()) { + d->activeStroker->setClipRect(d->exDeviceRect); + } else { + QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); + d->activeStroker->setClipRect(clipRect); + } + } + const QPainterPath::ElementType *types = path.elements(); const qreal *points = path.points(); int pointCount = path.elementCount(); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a98ac10..cde6a2d 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1374,9 +1374,6 @@ void QPainterPrivate::updateState(QPainterState *newState) opacity with non-smooth transformation mode (\c QPainter::SmoothPixmapTransform not enabled as a render hint). - \o Text drawing with regular font sizes with simple - transformations with solid colors using no or 8-bit antialiasing. - \o Rectangle fills with solid color, two-color linear gradients and simple transforms. @@ -1984,9 +1981,14 @@ QPaintEngine *QPainter::paintEngine() const /*! \since 4.6 - Flushes the painting pipeline and prepares for the user issuing - commands directly to the underlying graphics context. Must be - followed by a call to endNativePainting(). + Flushes the painting pipeline and prepares for the user issuing commands + directly to the underlying graphics context. Must be followed by a call to + endNativePainting(). + + Note that only the states the underlying paint engine changes will be reset + to their respective default states. If, for example, the OpenGL polygon + mode is changed by the user inside a beginNativePaint()/endNativePainting() + block, it will not be reset to the default state by endNativePainting(). Here is an example that shows intermixing of painter commands and raw OpenGL commands: @@ -2010,9 +2012,9 @@ void QPainter::beginNativePainting() /*! \since 4.6 - Restores the painter after manually issuing native painting commands. - Lets the painter restore any native state that it relies on before - calling any other painter commands. + Restores the painter after manually issuing native painting commands. Lets + the painter restore any native state that it relies on before calling any + other painter commands. \sa beginNativePainting() */ @@ -7380,10 +7382,15 @@ struct QPaintDeviceRedirection typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList; Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections) Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) +Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic) /*! \threadsafe + \obsolete + + Please use QWidget::render() instead. + Redirects all paint commands for the given paint \a device, to the \a replacement device. The optional point \a offset defines an offset within the source device. @@ -7393,9 +7400,10 @@ Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) device's painter (if any) before redirecting. Call restoreRedirected() to restore the previous redirection. - In general, you'll probably find that calling - QPixmap::grabWidget() or QPixmap::grabWindow() is an easier - solution. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. \sa redirected(), restoreRedirected() */ @@ -7427,14 +7435,24 @@ void QPainter::setRedirected(const QPaintDevice *device, Q_ASSERT(redirections != 0); *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset, hadInternalWidgetRedirection ? redirections->size() - 1 : -1); + globalRedirectionAtomic()->ref(); } /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Restores the previous redirection for the given \a device after a call to setRedirected(). + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa redirected() */ void QPainter::restoreRedirected(const QPaintDevice *device) @@ -7445,6 +7463,7 @@ void QPainter::restoreRedirected(const QPaintDevice *device) Q_ASSERT(redirections != 0); for (int i = redirections->size()-1; i >= 0; --i) { if (redirections->at(i) == device) { + globalRedirectionAtomic()->deref(); const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex; redirections->removeAt(i); // Restore the internal widget redirection, i.e. remove it from the global @@ -7466,9 +7485,18 @@ void QPainter::restoreRedirected(const QPaintDevice *device) /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Returns the replacement for given \a device. The optional out parameter \a offset returns the offset within the replaced device. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa setRedirected(), restoreRedirected() */ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) @@ -7481,6 +7509,9 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) return widgetPrivate->redirected(offset); } + if (*globalRedirectionAtomic() == 0) + return 0; + QMutexLocker locker(globalRedirectionsMutex()); QPaintDeviceRedirectionList *redirections = globalRedirections(); Q_ASSERT(redirections != 0); @@ -7498,6 +7529,9 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { + if (*globalRedirectionAtomic() == 0) + return; + QMutex *mutex = 0; QT_TRY { mutex = globalRedirectionsMutex(); diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp index e3a2461..b8bf15e 100644 --- a/src/gui/painting/qprintengine_pdf.cpp +++ b/src/gui/painting/qprintengine_pdf.cpp @@ -931,14 +931,24 @@ void QPdfEnginePrivate::writeHeader() void QPdfEnginePrivate::writeInfo() { info = addXrefEntry(-1); - xprintf("<<\n" - "/Title (%s)\n" -// "/Author (%s)\n" - "/Creator (%s)\n" - "/Producer (Qt " QT_VERSION_STR " (C) 2009 Nokia Corporation and/or its subsidiary(-ies))\n", - title.toUtf8().constData(), -// author.toUtf8().constData(), - creator.toUtf8().constData()); + + // The 'text string' type in PDF is encoded either as PDFDocEncoding, or + // Unicode UTF-16 with a Unicode byte order mark as the first character + // (0xfeff), with the high-order byte first. + QByteArray array("<<\n/Title (\xfe\xff"); + const ushort *utf16Title = title.utf16(); + for (int i=0; i < title.size(); ++i) { + array.append((*(utf16Title + i)) >> 8); + array.append((*(utf16Title + i)) & 0xff); + } + array.append(")\n/Creator (\xfe\xff"); + const ushort *utf16Creator = creator.utf16(); + for (int i=0; i < creator.size(); ++i) { + array.append((*(utf16Creator + i)) >> 8); + array.append((*(utf16Creator + i)) & 0xff); + } + array.append(")\n/Producer (Qt " QT_VERSION_STR " (C) 2010 Nokia Corporation and/or its subsidiary(-ies))\n"); + write(array); QDateTime now = QDateTime::currentDateTime().toUTC(); QTime t = now.time(); diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index b8eaead..b41dc2c 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -145,10 +145,12 @@ QImage* QS60WindowSurface::buffer(const QWidget *widget) void QS60WindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &) { - const QVector<QRect> subRects = region.rects(); - for (int i = 0; i < subRects.count(); ++i) { - TRect tr = qt_QRect2TRect(subRects[i]); + QWExtra *extra = widget->d_func()->extraData(); + if (extra && !extra->inExpose) { + extra->inExpose = true; // Prevent DrawNow() from calling syncBackingStore() again + TRect tr = qt_QRect2TRect(region.boundingRect()); widget->winId()->DrawNow(tr); + extra->inExpose = false; } } diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index abb9e1e..b5f052b 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -1106,8 +1106,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, // ### Note: Ubuntulooks breaks when the proper widget is passed // Murrine engine requires a widget not to get RGBA check - warnings GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); - gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, gtkRadioButton->style, QLS("radiobutton")); - + QString key(QLS("radiobutton")); + if (option->state & State_HasFocus) { // Themes such as Nodoka check this flag + key += QLatin1Char('f'); + GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } + gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, gtkRadioButton->style, key); + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); } break; @@ -1128,6 +1134,11 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, int spacing; GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); + QString key(QLS("checkbutton")); + if (option->state & State_HasFocus) { // Themes such as Nodoka checks this flag + key += QLatin1Char('f'); + GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } // Some styles such as aero-clone assume they can paint in the spacing area gtkPainter.setClipRect(option->rect); @@ -1137,7 +1148,10 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, QRect checkRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); gtkPainter.paintCheckbox(gtkCheckButton, checkRect, state, shadow, gtkCheckButton->style, - QLS("checkbutton")); + key); + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } break; @@ -1377,7 +1391,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom else { gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect, option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, - GTK_SHADOW_NONE, gtkCombo->style, entryPath + QString::number(focus)); + GTK_SHADOW_NONE, gtkEntry->style, entryPath + QString::number(focus)); } gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState, diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index ca0b8c7..ecb3242 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -68,6 +68,10 @@ #include "qtoolbutton.h" #include "qfocusframe.h" #include "qformlayout.h" +#include "qradiobutton.h" +#include "qcheckbox.h" +#include "qdesktopwidget.h" +#include "qprogressbar.h" #include "private/qtoolbarextension_p.h" #include "private/qcombobox_p.h" @@ -564,9 +568,11 @@ QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part, const QSize &size, QPainter *painter, SkinElementFlags flags) { QPixmap result; + const int animationFrame = (flags & SF_Animation) ? currentAnimationFrame(part) : 0; + const QString cacheKey = - QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4") - .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags); + QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4 AnimationFrame=%5") + .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags).arg(animationFrame); if (!QPixmapCache::find(cacheKey, result)) { result = QS60StylePrivate::part(part, size, painter, flags); QPixmapCache::insert(cacheKey, result); @@ -672,8 +678,7 @@ void QS60StylePrivate::setThemePalette(QPalette *palette) const s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0)); // set background image as a texture brush palette->setBrush(QPalette::Window, backgroundTexture()); - // set these as transparent so that styled full screen theme background is visible - palette->setColor(QPalette::AlternateBase, Qt::transparent); + // set as transparent so that styled full screen theme background is visible palette->setBrush(QPalette::Base, Qt::transparent); // set button and tooltipbase based on pixel colors const QColor buttonColor = colorFromFrameGraphics(SF_ButtonNormal); @@ -685,6 +690,9 @@ void QS60StylePrivate::setThemePalette(QPalette *palette) const palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125)); palette->setColor(QPalette::Mid, palette->color(QPalette::Button).darker(150)); palette->setColor(QPalette::Shadow, Qt::black); + QColor alternateBase = palette->light().color(); + alternateBase.setAlphaF(0.8); + palette->setColor(QPalette::AlternateBase, alternateBase); QApplication::setPalette(*palette); //calling QApplication::setPalette clears palette hash setThemePaletteHash(palette); @@ -775,6 +783,11 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const QApplication::setPalette(widgetPalette, "QComboBox"); widgetPalette = *palette; + widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 7, 0)); + QApplication::setPalette(widgetPalette, "QRadioButton"); + QApplication::setPalette(widgetPalette, "QCheckBox"); + widgetPalette = *palette; + widgetPalette.setColor(QPalette::WindowText, mainAreaTextColor); widgetPalette.setColor(QPalette::Button, QApplication::palette().color(QPalette::Button)); widgetPalette.setColor(QPalette::Dark, mainAreaTextColor.darker()); @@ -813,13 +826,13 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones). result.setWidth(result.height() >> 1); break; - + case QS60StyleEnums::SP_QgnGrafNsliderEndLeft: case QS60StyleEnums::SP_QgnGrafNsliderEndRight: case QS60StyleEnums::SP_QgnGrafNsliderMiddle: result.setWidth(result.height() >> 1); break; - + case QS60StyleEnums::SP_QgnGrafNsliderMarker: case QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected: result.scale(pixelMetric(QStyle::PM_SliderLength), @@ -922,10 +935,10 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom horizontal ? QS60StylePrivate::SE_ScrollBarGrooveHorizontal : QS60StylePrivate::SE_ScrollBarGrooveVertical; QS60StylePrivate::drawSkinElement(grooveElement, painter, grooveRect, flags); - const QStyle::SubControls subControls = optionSlider->subControls; + const SubControls subControls = optionSlider->subControls; // select correct slider (horizontal/vertical/pressed) - const bool sliderPressed = ((optionSlider->state & QStyle::State_Sunken) && (subControls & SC_ScrollBarSlider)); + const bool sliderPressed = ((optionSlider->state & State_Sunken) && (subControls & SC_ScrollBarSlider)); const QS60StylePrivate::SkinElements handleElement = horizontal ? ( sliderPressed ? @@ -946,13 +959,13 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom const bool horizontal = optionSlider->orientation == Qt::Horizontal; //Highlight -/* if (optionSlider->state & QStyle::State_HasFocus) +/* if (optionSlider->state & State_HasFocus) drawPrimitive(PE_FrameFocusRect, optionSlider, painter, widget);*/ - + //Groove graphics if (QS60StylePrivate::hasSliderGrooveGraphic()) { - const QS60StylePrivate::SkinElements grooveElement = horizontal ? - QS60StylePrivate::SE_SliderGrooveHorizontal : + const QS60StylePrivate::SkinElements grooveElement = horizontal ? + QS60StylePrivate::SE_SliderGrooveHorizontal : QS60StylePrivate::SE_SliderGrooveVertical; QS60StylePrivate::drawSkinElement(grooveElement, painter, sliderGroove, flags); } else { @@ -975,7 +988,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom if (optionSlider->state & QStyle::State_Sunken) handleElement = horizontal ? QS60StylePrivate::SE_SliderHandleSelectedHorizontal : QS60StylePrivate::SE_SliderHandleSelectedVertical; - else + else handleElement = horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical; QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags); @@ -994,7 +1007,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom buttonOption.QStyleOption::operator=(*cmb); const int maxHeight = cmbxFrame.height(); const int maxWidth = cmbxFrame.width() - cmbxEditField.width(); - const int topLeftPoint = direction ? + const int topLeftPoint = direction ? (cmbxEditField.right() + 1) : (cmbxEditField.left() + 1 - maxWidth); const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight); buttonOption.rect = buttonRect; @@ -1020,102 +1033,62 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom #ifndef QT_NO_TOOLBUTTON case CC_ToolButton: if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { - const State bflags = toolBtn->state; + State bflags = toolBtn->state & ~State_Sunken; + + if (bflags & State_AutoRaise) { + if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { + bflags &= ~State_Raised; + } + } + State mflags = bflags; + if (toolBtn->state & State_Sunken) { + if (toolBtn->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + mflags |= State_Sunken; + } + const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget)); QRect menuRect = QRect(); if (toolBtn->subControls & SC_ToolButtonMenu) menuRect = subControlRect(control, toolBtn, SC_ToolButtonMenu, widget); - QStyleOptionToolButton toolButton = *toolBtn; - - if (sub&SC_ToolButton) { + if (toolBtn->subControls & SC_ToolButton) { QStyleOption tool(0); tool.palette = toolBtn->palette; - // Check if toolbutton is in toolbar. - QToolBar *toolBar = 0; - if (widget) - toolBar = qobject_cast<QToolBar *>(widget->parentWidget()); - - if (bflags & (State_Sunken | State_On | State_Raised)) { + if (bflags & (State_Sunken | State_On | State_Raised | State_Enabled)) { tool.rect = button.unite(menuRect); tool.state = bflags; - - // todo: I'd like to move extension button next to where last button is - // however, the painter seems to want to clip the button rect even if I turn of the clipping. - if (toolBar && (qobject_cast<const QToolBarExtension *>(widget))){ - /*QList<QAction *> actionList = toolBar->actions(); - const int actionCount = actionList.count(); - const int toolbarWidth = toolBar->width(); - const int extButtonWidth = pixelMetric(PM_ToolBarExtensionExtent, option, widget); - const int toolBarButtonWidth = pixelMetric(PM_ToolBarIconSize, option, widget); - const int frame = pixelMetric(PM_ToolBarFrameWidth, option, widget); - const int margin = pixelMetric(PM_ToolBarItemMargin, option, widget); - const int border = frame + margin; - const int spacing = pixelMetric(PM_ToolBarItemSpacing, option, widget); - const int toolBarButtonArea = toolbarWidth - extButtonWidth - spacing - 2*border; - const int numberOfVisibleButtons = toolBarButtonArea / toolBarButtonWidth; - // new extension button place is after border and all the other visible buttons (with spacings) - const int newXForExtensionButton = numberOfVisibleButtons * toolBarButtonWidth + (numberOfVisibleButtons-1)*spacing + border; - painter->save(); - painter->setClipping(false); - tool.rect.translate(-newXForExtensionButton,0); - painter->restore();*/ - } - - if (toolBar){ - /*if (toolBar->orientation() == Qt::Vertical){ - // todo: I'd like to make all vertical buttons the same size, but again the painter - // prefers to use clipping for button rects, even though clipping has been set off. - painter->save(); - painter->setClipping(false); - - const int origWidth = tool.rect.width(); - const int newWidth = toolBar->width()-2*pixelMetric(PM_ToolBarFrameWidth, option, widget); - painter->translate(origWidth-newWidth,0); - tool.rect.translate(origWidth-tool.rect.width(),0); - tool.rect.setWidth(newWidth); - - if (option->state & QStyle::State_Sunken) - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags); - else - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags); - - }*/ - if (option->state & QStyle::State_Sunken) - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags); - else - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags); - /* - if (toolBar->orientation() == Qt::Vertical) - painter->restore(); - */ - } else { - drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); - } - - if (toolButton.subControls & SC_ToolButtonMenu) { - tool.rect = menuRect; - tool.state = bflags; - drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); - } + const QToolButton *toolButtonWidget = qobject_cast<const QToolButton *>(widget); + QS60StylePrivate::SkinElements element; + if (toolButtonWidget) + element = (toolButtonWidget->isDown()) ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; + else + element = (option->state & State_Sunken) ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; + QS60StylePrivate::drawSkinElement(element, painter, tool.rect, flags); + drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + if (toolBtn->subControls & SC_ToolButtonMenu) { + tool.rect = menuRect; + tool.state = mflags; + drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); } } - + QStyleOptionToolButton toolButton = *toolBtn; if (toolBtn->features & QStyleOptionToolButton::Arrow) { - QStyle::PrimitiveElement pe; + PrimitiveElement pe; switch (toolBtn->arrowType) { case Qt::LeftArrow: - pe = QStyle::PE_IndicatorArrowLeft; + pe = PE_IndicatorArrowLeft; break; case Qt::RightArrow: - pe = QStyle::PE_IndicatorArrowRight; + pe = PE_IndicatorArrowRight; break; case Qt::UpArrow: - pe = QStyle::PE_IndicatorArrowUp; + pe = PE_IndicatorArrowUp; break; case Qt::DownArrow: - pe = QStyle::PE_IndicatorArrowDown; + pe = PE_IndicatorArrowDown; break; default: break; } @@ -1199,7 +1172,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom // Draw frame const QRect textRect = subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget); const QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget); - if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + if (groupBox->subControls & SC_GroupBoxFrame) { QStyleOptionFrameV2 frame; frame.QStyleOption::operator=(*groupBox); frame.features = groupBox->features; @@ -1210,14 +1183,14 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom } // Draw title - if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + if ((groupBox->subControls & SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { const QColor textColor = groupBox->textColor; painter->save(); if (textColor.isValid()) painter->setPen(textColor); int alignment = int(groupBox->textAlignment); - if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + if (!styleHint(SH_UnderlineShortcut, option, widget)) alignment |= Qt::TextHideMnemonic; drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | Qt::AlignVCenter | alignment, @@ -1249,6 +1222,31 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, Q_D(const QS60Style); const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; switch (element) { + case CE_CheckBox: + case CE_RadioButton: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + bool isRadio = (element == CE_RadioButton); + // Highlight needs to be drawn first, as it goes "underneath" the text and indicator. + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, btn, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + QStyleOptionButton subopt = *btn; + + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, painter, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + + drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget); + } + break; + case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { @@ -1261,13 +1259,13 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, break; case CE_PushButtonBevel: if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { - const bool isDisabled = !(option->state & QStyle::State_Enabled); + const bool isDisabled = !(option->state & State_Enabled); const bool isFlat = button->features & QStyleOptionButton::Flat; QS60StyleEnums::SkinParts skinPart; QS60StylePrivate::SkinElements skinElement; if (!isDisabled) { - const bool isPressed = (option->state & QStyle::State_Sunken) || - (option->state & QStyle::State_On); + const bool isPressed = (option->state & State_Sunken) || + (option->state & State_On); if (isFlat) { skinPart = isPressed ? QS60StyleEnums::SP_QsnFrButtonTbCenterPressed : QS60StyleEnums::SP_QsnFrButtonTbCenter; @@ -1292,7 +1290,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { QStyleOptionToolButton optionToolButton = *toolBtn; - if (!optionToolButton.icon.isNull() && (optionToolButton.state & QStyle::State_Sunken) + if (!optionToolButton.icon.isNull() && (optionToolButton.state & State_Sunken) && (optionToolButton.state & State_Enabled)) { const QIcon::State state = optionToolButton.state & State_On ? QIcon::On : QIcon::Off; @@ -1351,8 +1349,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->save(); painter->setClipRect(voptAdj.rect); - const bool isSelected = (vopt->state & QStyle::State_Selected); - const bool hasFocus = (vopt->state & QStyle::State_HasFocus); + const bool isSelected = (vopt->state & State_Selected); + const bool hasFocus = (vopt->state & State_HasFocus); bool isScrollBarVisible = false; int scrollBarWidth = 0; @@ -1426,8 +1424,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, } // draw the icon - const QIcon::Mode mode = (voptAdj.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled; - const QIcon::State state = voptAdj.state & QStyle::State_Open ? QIcon::On : QIcon::Off; + const QIcon::Mode mode = (voptAdj.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled; + const QIcon::State state = voptAdj.state & State_Open ? QIcon::On : QIcon::Off; voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); // Draw selection check mark. Show check mark only in multi selection modes. @@ -1439,29 +1437,29 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QStyleOptionViewItemV4 checkMarkOption(voptAdj); // Draw selection mark. - if (voptAdj.state & QStyle::State_Selected && !singleSelection) { + if (voptAdj.state & State_Selected && !singleSelection) { checkMarkOption.rect = selectionRect; - drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); + drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); if ( textRect.right() > selectionRect.left() ) textRect.setRight(selectionRect.left()); } else if (singleSelection && voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator && selectionRect.isValid()) { checkMarkOption.rect = selectionRect; - checkMarkOption.state = checkMarkOption.state & ~QStyle::State_HasFocus; + checkMarkOption.state = checkMarkOption.state & ~State_HasFocus; switch (vopt->checkState) { case Qt::Unchecked: - checkMarkOption.state |= QStyle::State_Off; + checkMarkOption.state |= State_Off; break; case Qt::PartiallyChecked: - checkMarkOption.state |= QStyle::State_NoChange; + checkMarkOption.state |= State_NoChange; break; case Qt::Checked: - checkMarkOption.state |= QStyle::State_On; + checkMarkOption.state |= State_On; break; } - drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); + drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); } } @@ -1486,7 +1484,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, case CE_TabBarTabShape: if (const QStyleOptionTabV3 *optionTab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) { QStyleOptionTabV3 optionTabAdj = *optionTab; - const bool isSelected = optionTab->state & QStyle::State_Selected; + const bool isSelected = optionTab->state & State_Selected; const bool directionMirrored = (optionTab->direction == Qt::RightToLeft); QS60StylePrivate::SkinElements skinElement; switch (optionTab->shape) { @@ -1521,9 +1519,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, skinElement==QS60StylePrivate::SE_TabBarTabSouthActive|| skinElement==QS60StylePrivate::SE_TabBarTabWestActive) { const int borderThickness = - QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth); + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); const int tabOverlap = - QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness; + QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness; //todo: draw navi wipe behind tabbar - must be drawn with first draw if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive|| @@ -1546,9 +1544,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QStyleOptionTabV3 optionTab = *tab; QRect tr = optionTab.rect; const bool directionMirrored = (optionTab.direction == Qt::RightToLeft); - const int borderThickness = QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth); + const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); const int tabOverlap = - QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness; + QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness; const QRect windowRect = painter->window(); switch (tab->shape) { @@ -1602,12 +1600,12 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, m.rotate(newRotation); painter->setTransform(m, true); } - tr.adjust(0, 0, pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget), - pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget)); + tr.adjust(0, 0, pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget), + pixelMetric(PM_TabBarTabShiftVertical, tab, widget)); if (selected) { - tr.setBottom(tr.bottom() - pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget)); - tr.setRight(tr.right() - pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget)); + tr.setBottom(tr.bottom() - pixelMetric(PM_TabBarTabShiftVertical, tab, widget)); + tr.setRight(tr.right() - pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget)); } int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; @@ -1648,17 +1646,20 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, // busy indicator const QS60StylePrivate::SkinElementFlag orientationFlag = optionProgressBar->orientation == Qt::Horizontal ? QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointWest; - QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWait, painter, progressRect, flags | orientationFlag); + + QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWaitAnim, + painter, progressRect, flags | orientationFlag | QS60StylePrivate::SF_Animation ); } else { const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0 : (qreal)optionProgressBar->progress / optionProgressBar->maximum; + const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget); if (optionProgressBar->orientation == Qt::Horizontal) { progressRect.setWidth(int(progressRect.width() * progressFactor)); if(optionProgressBar->direction == Qt::RightToLeft) - progressRect.translate(optionProgressBar->rect.width()-progressRect.width(), 0); - progressRect.adjust(1, 0, -1, 0); + progressRect.translate(optionProgressBar->rect.width() - progressRect.width(), 0); + progressRect.adjust(frameWidth, 0, -frameWidth, 0); } else { - progressRect.adjust(0, 1, 0, -1); + progressRect.adjust(0, frameWidth, 0, -frameWidth); progressRect.setTop(progressRect.bottom() - int(progressRect.height() * progressFactor)); } @@ -1714,9 +1715,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget); //todo: move the vertical spacing stuff into subElementRect - const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); + const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing); if (checkable){ - const int hSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + const int hSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing); QStyleOptionMenuItem optionCheckBox; optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem); optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth)); @@ -1754,7 +1755,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QStyleOptionMenuItem arrowOptions; arrowOptions.QStyleOption::operator=(*menuItem); const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget) >> 1) + - pixelMetric(QStyle::PM_LayoutVerticalSpacing, option, widget); + pixelMetric(PM_LayoutVerticalSpacing, option, widget); if (optionMenuItem.direction == Qt::LeftToRight) arrowOptions.rect.setLeft(textRect.right()); arrowOptions.rect.setWidth(indicatorWidth); @@ -1925,8 +1926,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, break; case CE_MenuScroller: break; - case CE_FocusFrame: - { + case CE_FocusFrame: { // The pen width should nearly fill the layoutspacings around the widget const int penWidth = qMin(pixelMetric(QS60Style::PM_LayoutVerticalSpacing), pixelMetric(QS60Style::PM_LayoutHorizontalSpacing)) @@ -1985,11 +1985,21 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, */ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { - Q_D(const QS60Style); const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; bool commonStyleDraws = false; switch (element) { + case PE_FrameFocusRect: { + //Draw themed highlight to radiobuttons and checkboxes. + //For other widgets skip, unless palette has been modified. In that case, draw with commonstyle. + if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) + if ((qstyleoption_cast<const QStyleOptionFocusRect *>(option) && + (qobject_cast<const QRadioButton *>(widget) || qobject_cast<const QCheckBox *>(widget)))) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + else + commonStyleDraws = true; + } + break; #ifndef QT_NO_LINEEDIT case PE_PanelLineEdit: if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) { @@ -2004,15 +2014,14 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti } break; #endif // QT_NO_LINEEDIT - case PE_IndicatorCheckBox: - { + case PE_IndicatorCheckBox: { // Draw checkbox indicator as color skinned graphics. - const QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? + const QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ? QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff; painter->save(); - QColor themeColor = QS60StylePrivate::themePalette()->windowText().color(); - QColor windowTextColor = option->palette.windowText().color(); + const QColor themeColor = QS60StylePrivate::themePalette()->windowText().color(); + const QColor windowTextColor = option->palette.windowText().color(); if (themeColor != windowTextColor) painter->setPen(windowTextColor); @@ -2032,7 +2041,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti if (checkBoxVisible && singleSelection) { drawPrimitive(PE_IndicatorCheckBox, option, painter, widget); // ... or normal "tick" selection at the end. - } else if (option->state & QStyle::State_Selected) { + } else if (option->state & State_Selected) { QRect tickRect = option->rect; const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth); // adjust tickmark rect to exclude frame border @@ -2059,15 +2068,15 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti buttonRect.adjust(0, -newY, -1, -newY); painter->save(); - QColor themeColor = d->s60Color(QS60StyleEnums::CL_QsnTextColors, 6, option); - QColor buttonTextColor = option->palette.buttonText().color(); + const QColor themeColor = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, option); + const QColor buttonTextColor = option->palette.buttonText().color(); if (themeColor != buttonTextColor) painter->setPen(buttonTextColor); else painter->setPen(themeColor); // Draw radiobutton indicator as color skinned graphics. - QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? + QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ? QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff; QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect, (flags | QS60StylePrivate::SF_ColorSkinned)); @@ -2077,15 +2086,14 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_PanelButtonCommand: case PE_PanelButtonTool: case PE_PanelButtonBevel: - case PE_FrameButtonBevel: { + case PE_FrameButtonBevel: if (QS60StylePrivate::canDrawThemeBackground(option->palette.base())) { - const bool isPressed = option->state & QStyle::State_Sunken; + const bool isPressed = option->state & State_Sunken; const QS60StylePrivate::SkinElements skinElement = isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); } else { commonStyleDraws = true; - } } break; #ifndef QT_NO_TOOLBUTTON @@ -2207,7 +2215,6 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti break; #ifndef QT_NO_ITEMVIEWS case PE_PanelItemViewItem: - case PE_PanelItemViewRow: // ### Qt 5: remove break; #endif //QT_NO_ITEMVIEWS @@ -2276,7 +2283,23 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti } } break; - + case PE_PanelItemViewRow: // ### Qt 5: remove +#ifndef QT_NO_ITEMVIEWS + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { + if (vopt->palette.base().texture().cacheKey() != QS60StylePrivate::m_themePalette->base().texture().cacheKey()) { + //QPalette::Base has been changed, let commonstyle draw the item + commonStyleDraws = true; + } else { + QPalette::ColorGroup cg = vopt->state & State_Enabled ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & State_Active)) + cg = QPalette::Inactive; + if (vopt->features & QStyleOptionViewItemV2::Alternate) + painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase)); + //apart from alternate base, no background for list item is drawn for S60Style + } + } +#endif + break; case PE_PanelScrollAreaCorner: break; @@ -2361,8 +2384,7 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) sz += QSize(2 * f->lineWidth, 4 * f->lineWidth); break; - case CT_TabBarTab: - { + case CT_TabBarTab: { const QSize naviPaneSize = QS60StylePrivate::naviPaneSize(); sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); if (naviPaneSize.height() > sz.height()) @@ -2374,8 +2396,26 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, if (QS60StylePrivate::isTouchSupported()) //Make itemview easier to use in touch devices //QCommonStyle does not adjust height with horizontal margin, it only adjusts width - sz.setHeight(sz.height() + 2 * pixelMetric(QStyle::PM_FocusFrameVMargin)); + sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin)); break; +#ifndef QT_NO_COMBOBOX + case CT_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { + const int frameWidth = cmb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0; + const int textMargins = 2*(pixelMetric(PM_FocusFrameHMargin) + 1); + const int smallestExtraWidth = 23; + // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins... + const int extra = + qMax(smallestExtraWidth, 2*textMargins + pixelMetric(PM_ScrollBarExtent, opt, widget)); + sz = QSize(sz.width() + frameWidth + extra, sz.height() + frameWidth); + int maxScreenWidth = QApplication::desktop()->availableGeometry().size().width(); + if (sz.width() > maxScreenWidth) { + maxScreenWidth = maxScreenWidth - (extra + frameWidth); + sz.setWidth(maxScreenWidth); + } + } + break; +#endif default: sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); break; @@ -2414,7 +2454,7 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w retValue = QPalette::Base; break; case SH_ItemView_ActivateItemOnSingleClick: - retValue = true; + retValue = QS60StylePrivate::isSingleClickUi(); break; case SH_ProgressDialog_TextLabelAlignment: retValue = (QApplication::layoutDirection() == Qt::LeftToRight) ? @@ -2526,7 +2566,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; const int buttonMargin = spinbox->frame ? 2 : 0; - const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2 * buttonMargin; + const int buttonWidth = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin; QSize buttonSize; buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness)); //width should at least be equal to height @@ -2575,7 +2615,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple ret = cmb->rect; const int width = cmb->rect.width(); const int height = cmb->rect.height(); - const int buttonIconSize = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize); + const int buttonIconSize = QS60StylePrivate::pixelMetric(PM_ButtonIconSize); const int buttonMargin = cmb->frame ? 2 : 0; // lets use spinbox frame here as well, as no combobox specific value available. const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0; @@ -2613,7 +2653,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple case SC_GroupBoxLabel: { //slightly indent text and boxes, so that dialog border does not mess with them. const int horizontalSpacing = - QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing); ret.adjust(2, horizontalSpacing - 3, 0, 0); } break; @@ -2668,6 +2708,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con { QRect ret; switch (element) { + case SE_RadioButtonFocusRect: + ret = opt->rect; + break; case SE_LineEditContents: { // in S60 the input text box doesn't start from line Edit's TL, but // a bit indented. @@ -2686,9 +2729,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { const int tabOverlapNoBorder = - QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap); + QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap); const int tabOverlap = - tabOverlapNoBorder-QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth); + tabOverlapNoBorder-QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget); int gain = (tab) ? tabOverlap * tab->count() : 0; switch (twf->shape) { @@ -2737,8 +2780,8 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con multiSelection && (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)) { const int verticalSpacing = - QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); - //const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing); + //const int horizontalSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing); const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width(); ret.adjust(-checkBoxRectWidth - verticalSpacing, 0, -checkBoxRectWidth - verticalSpacing, 0); } @@ -2784,9 +2827,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con singleSelection; // Selection check mark rect. - const int indicatorWidth = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorWidth); - const int indicatorHeight = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorHeight); - const int spacing = QS60StylePrivate::pixelMetric(QStyle::PM_CheckBoxLabelSpacing); + const int indicatorWidth = QS60StylePrivate::pixelMetric(PM_IndicatorWidth); + const int indicatorHeight = QS60StylePrivate::pixelMetric(PM_IndicatorHeight); + const int spacing = QS60StylePrivate::pixelMetric(PM_CheckBoxLabelSpacing); const int itemHeight = opt->rect.height(); int heightOffset = 0; @@ -2818,6 +2861,25 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con } ret = visualRect(opt->direction, opt->rect, ret); break; + case SE_RadioButtonIndicator: { + const int height = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget); + ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1), + pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), height); + ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it + ret = visualRect(opt->direction, opt->rect, ret); + } + break; + case SE_CheckBoxIndicator: { + const int height = pixelMetric(PM_IndicatorHeight, opt, widget); + ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1), + pixelMetric(PM_IndicatorWidth, opt, widget), height); + ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it + ret = visualRect(opt->direction, opt->rect, ret); + } + break; + case SE_CheckBoxFocusRect: + ret = opt->rect; + break; default: ret = QCommonStyle::subElementRect(element, opt, widget); } @@ -2835,6 +2897,12 @@ void QS60Style::polish(QWidget *widget) if (!widget) return; + //Currently we only support animations in QProgressBar. +#ifndef QT_NO_PROGRESSBAR + if (qobject_cast<QProgressBar *>(widget)) + widget->installEventFilter(this); +#endif + if (false #ifndef QT_NO_SCROLLBAR || qobject_cast<QScrollBar *>(widget) @@ -2867,6 +2935,8 @@ void QS60Style::polish(QWidget *widget) */ void QS60Style::unpolish(QWidget *widget) { + Q_D(QS60Style); + if (false #ifndef QT_NO_SCROLLBAR || qobject_cast<QScrollBar *>(widget) @@ -2893,6 +2963,14 @@ void QS60Style::unpolish(QWidget *widget) if (widget) widget->setPalette(QPalette()); +#if defined(Q_WS_S60) && !defined(QT_NO_PROGRESSBAR) + if (QProgressBar *bar = qobject_cast<QProgressBar *>(widget)) { + widget->removeEventFilter(this); + d->m_bars.removeAll(bar); + } +#else + Q_UNUSED(d) +#endif QCommonStyle::unpolish(widget); } @@ -2924,10 +3002,23 @@ void QS60Style::unpolish(QApplication *application) bool QS60Style::event(QEvent *e) { #ifdef QT_KEYPAD_NAVIGATION - if (QS60StylePrivate::isTouchSupported()) - return false; Q_D(QS60Style); + const QEvent::Type eventType = e->type(); + if ((eventType == QEvent::FocusIn || + eventType == QEvent::FocusOut || + eventType == QEvent::EnterEditFocus || + eventType == QEvent::LeaveEditFocus) && + QS60StylePrivate::isTouchSupported()) + return false; +#endif + switch (e->type()) { + case QEvent::Timer: { + QTimerEvent *te = static_cast<QTimerEvent*>(e); + timerEvent(te); + } + break; +#ifdef QT_KEYPAD_NAVIGATION case QEvent::FocusIn: if (QWidget *focusWidget = QApplication::focusWidget()) { if (!d->m_focusFrame) @@ -2946,12 +3037,10 @@ bool QS60Style::event(QEvent *e) if (d->m_focusFrame) d->m_focusFrame->update(); break; +#endif default: break; } -#else - Q_UNUSED(e) -#endif return false; } @@ -2961,7 +3050,7 @@ bool QS60Style::event(QEvent *e) QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { - const int iconDimension = QS60StylePrivate::pixelMetric(QStyle::PM_ToolBarIconSize); + const int iconDimension = QS60StylePrivate::pixelMetric(PM_ToolBarIconSize); const QRect iconSize = (!option) ? QRect(0, 0, iconDimension, iconDimension) : option->rect; QS60StyleEnums::SkinParts part; QS60StylePrivate::SkinElementFlags adjustedFlags; @@ -2971,67 +3060,67 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, QS60StylePrivate::SF_StateDisabled; switch(standardIcon) { - case QStyle::SP_MessageBoxWarning: + case SP_MessageBoxWarning: part = QS60StyleEnums::SP_QgnNoteWarning; break; - case QStyle::SP_MessageBoxInformation: + case SP_MessageBoxInformation: part = QS60StyleEnums::SP_QgnNoteInfo; break; - case QStyle::SP_MessageBoxCritical: + case SP_MessageBoxCritical: part = QS60StyleEnums::SP_QgnNoteError; break; - case QStyle::SP_MessageBoxQuestion: + case SP_MessageBoxQuestion: part = QS60StyleEnums::SP_QgnNoteQuery; break; - case QStyle::SP_ArrowRight: + case SP_ArrowRight: part = QS60StyleEnums::SP_QgnIndiNaviArrowRight; break; - case QStyle::SP_ArrowLeft: + case SP_ArrowLeft: part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; break; - case QStyle::SP_ArrowUp: + case SP_ArrowUp: part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; adjustedFlags |= QS60StylePrivate::SF_PointEast; break; - case QStyle::SP_ArrowDown: + case SP_ArrowDown: part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; adjustedFlags |= QS60StylePrivate::SF_PointWest; break; - case QStyle::SP_ArrowBack: + case SP_ArrowBack: if (QApplication::layoutDirection() == Qt::RightToLeft) return QS60Style::standardIcon(SP_ArrowRight, option, widget); return QS60Style::standardIcon(SP_ArrowLeft, option, widget); - case QStyle::SP_ArrowForward: + case SP_ArrowForward: if (QApplication::layoutDirection() == Qt::RightToLeft) return QS60Style::standardIcon(SP_ArrowLeft, option, widget); return QS60Style::standardIcon(SP_ArrowRight, option, widget); - case QStyle::SP_ComputerIcon: + case SP_ComputerIcon: part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge; break; - case QStyle::SP_DirClosedIcon: + case SP_DirClosedIcon: part = QS60StyleEnums::SP_QgnPropFolderSmall; break; - case QStyle::SP_DirOpenIcon: + case SP_DirOpenIcon: part = QS60StyleEnums::SP_QgnPropFolderCurrent; break; - case QStyle::SP_DirIcon: + case SP_DirIcon: part = QS60StyleEnums::SP_QgnPropFolderSmall; break; - case QStyle::SP_FileDialogNewFolder: + case SP_FileDialogNewFolder: part = QS60StyleEnums::SP_QgnPropFolderSmallNew; break; - case QStyle::SP_FileIcon: + case SP_FileIcon: part = QS60StyleEnums::SP_QgnPropFileSmall; break; - case QStyle::SP_TrashIcon: + case SP_TrashIcon: part = QS60StyleEnums::SP_QgnNoteErased; break; - case QStyle::SP_ToolBarHorizontalExtensionButton: + case SP_ToolBarHorizontalExtensionButton: part = QS60StyleEnums::SP_QgnIndiSubMenu; if (QApplication::layoutDirection() == Qt::RightToLeft) adjustedFlags |= QS60StylePrivate::SF_PointSouth; break; - case QStyle::SP_ToolBarVerticalExtensionButton: + case SP_ToolBarVerticalExtensionButton: adjustedFlags |= QS60StylePrivate::SF_PointEast; part = QS60StyleEnums::SP_QgnIndiSubMenu; break; @@ -3045,6 +3134,68 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap); } +/*! + \internal + Animate indeterminate progress bars only when visible +*/ +bool QS60Style::eventFilter(QObject *object, QEvent *event) +{ +#ifdef Q_WS_S60 +#ifndef QT_NO_PROGRESSBAR + Q_D(QS60Style); + switch(event->type()) { + case QEvent::StyleChange: + case QEvent::Show: + if (QProgressBar *bar = qobject_cast<QProgressBar *>(object)) { + if (!d->m_bars.contains(bar)) + d->m_bars << bar; + if (d->m_bars.size() == 1) //only start with first animated progressbar + d->startAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + } + break; + case QEvent::Destroy: + case QEvent::Hide: + d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + d->m_bars.removeAll(reinterpret_cast<QProgressBar *>(object)); + break; + default: + break; + } +#endif // QT_NO_PROGRESSBAR +#endif // Q_WS_S60 + return QStyle::eventFilter(object, event); +} + +void QS60Style::timerEvent(QTimerEvent *event) +{ +#ifdef Q_WS_S60 +#ifndef QT_NO_PROGRESSBAR + Q_D(QS60Style); + + QS60StyleAnimation *progressBarAnimation = + QS60StylePrivate::animationDefinition(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + + if (event->timerId() == progressBarAnimation->timerId()) { + + Q_ASSERT(progressBarAnimation->interval() > 0); + + if (progressBarAnimation->currentFrame() == progressBarAnimation->frameCount() ) + if (progressBarAnimation->playMode() == QS60StyleEnums::AM_Looping) + progressBarAnimation->setCurrentFrame(0); + else + d->stopAnimation(progressBarAnimation->animationId()); + + foreach (QProgressBar *bar, d->m_bars) { + if ((bar->minimum() == 0 && bar->maximum() == 0)) + bar->update(); + } + progressBarAnimation->setCurrentFrame(progressBarAnimation->currentFrame() + 1); + } +#endif // QT_NO_PROGRESSBAR +#endif // Q_WS_S60 + event->ignore(); +} + extern QPoint qt_s60_fill_background_offset(const QWidget *targetWidget); bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) @@ -3056,11 +3207,13 @@ bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush const QPaintDevice *target = painter->device(); if (target->devType() == QInternal::Widget) { const QWidget *widget = static_cast<const QWidget *>(target); - const QVector<QRect> &rects = rgn.rects(); - for (int i = 0; i < rects.size(); ++i) { - const QRect rect(rects.at(i)); - painter->drawPixmap(rect.topLeft(), backgroundTexture, - rect.translated(qt_s60_fill_background_offset(widget))); + if (!widget->testAttribute(Qt::WA_TranslucentBackground)) { + const QVector<QRect> &rects = rgn.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect rect(rects.at(i)); + painter->drawPixmap(rect.topLeft(), backgroundTexture, + rect.translated(qt_s60_fill_background_offset(widget))); + } } } return true; diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h index adcb313..82cc21c 100644 --- a/src/gui/styles/qs60style.h +++ b/src/gui/styles/qs60style.h @@ -94,6 +94,9 @@ protected Q_SLOTS: QIcon standardIconImplementation( StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0 ) const; +protected: + void timerEvent(QTimerEvent *event); + bool eventFilter(QObject *o, QEvent *e); private: Q_DISABLE_COPY(QS60Style) friend class QStyleFactory; diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 1417552..2cd238f 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -93,6 +93,29 @@ class QS60StyleEnums #endif // !Q_WS_S60 public: + + // S60 definitions within theme + enum ThemeDefinitions { + TD_AnimationData, + }; + + //Defines which values are contained within animation data (retrieved using TD_AnimationData). + //Additionally defines the order in which the items are given out in QList<QVariant>. + enum AnimationData { + AD_Interval = 0, + AD_NumberOfFrames, + AD_AnimationPlayMode, //currently not used as themes seem to contain invalid data + }; + + // Animation modes + enum AnimationMode { + AM_PlayOnce = 0, //animation is played exactly once + AM_Looping, //animation is repeated until stopped + AM_Bounce //animation is played repeatedly until stopped, + //but frames are played in reverse order every second time + //(no support yet) + }; + // S60 look-and-feel font categories enum FontCategories { FC_Undefined, @@ -104,7 +127,7 @@ public: }; enum SkinParts { - SP_QgnGrafBarWait, + SP_QgnGrafBarWaitAnim, SP_QgnGrafBarFrameCenter, SP_QgnGrafBarFrameSideL, SP_QgnGrafBarFrameSideR, @@ -287,7 +310,70 @@ public: }; }; +#ifdef Q_WS_S60 +class CAknBitmapAnimation; +NONSHARABLE_CLASS (AnimationData) : public QObject +{ +public: + AnimationData(const QS60StyleEnums::SkinParts part, int frames, int interval); + + const QS60StyleEnums::SkinParts m_id; + int m_frames; + int m_interval; + QS60StyleEnums::AnimationMode m_mode; +}; + + +NONSHARABLE_CLASS (AnimationDataV2) : public AnimationData +{ +public: + AnimationDataV2(const AnimationData &data); + ~AnimationDataV2(); + + CAknBitmapAnimation *m_animation; + int m_currentFrame; + bool m_resourceBased; + int m_timerId; +}; + + +class QS60StyleAnimation : public QObject +{ +public: + QS60StyleAnimation(const QS60StyleEnums::SkinParts part, int frames, int interval); + ~QS60StyleAnimation(); + +public: + QS60StyleEnums::SkinParts animationId() const {return m_currentData->m_id;} + int frameCount() const { return m_currentData->m_frames;} + int interval() const {return m_currentData->m_interval;} + QS60StyleEnums::AnimationMode playMode() const {return m_currentData->m_mode;} + CAknBitmapAnimation* animationObject() const {return m_currentData->m_animation;} + bool isResourceBased() const {return m_currentData->m_resourceBased;} + int timerId() const {return m_currentData->m_timerId;} + int currentFrame() const {return m_currentData->m_currentFrame;} + + void setFrameCount(const int &frameCount) {m_currentData->m_frames = frameCount;} + void setInterval(const int &interval) {m_currentData->m_interval = interval;} + void setAnimationObject(CAknBitmapAnimation* animation); + void setResourceBased(bool resourceBased) {m_currentData->m_resourceBased = resourceBased;} + void setTimerId(const int &timerId) {m_currentData->m_timerId = timerId;} + void setCurrentFrame(const int ¤tFrame) {m_currentData->m_currentFrame = currentFrame;} + + void resetToDefaults(); + +private: //data members + //TODO: consider changing these to non-pointers as the classes are rather small anyway + AnimationData *m_defaultData; + AnimationDataV2 *m_currentData; +}; + +#endif //Q_WS_S60 + + class QFocusFrame; +class QProgressBar; +class QS60StyleAnimation; // Private class #ifdef Q_OS_SYMBIAN @@ -371,6 +457,7 @@ public: SF_StateEnabled = 0x0010, // Enabled = the default SF_StateDisabled = 0x0020, SF_ColorSkinned = 0x0040, // pixmap is colored with foreground pen color + SF_Animation = 0x0080, }; enum CacheClearReason { @@ -412,6 +499,7 @@ public: static bool isTouchSupported(); static bool isToolBarBackground(); static bool hasSliderGrooveGraphic(); + static bool isSingleClickUi(); // calculates average color based on button skin graphics (minus borders). QColor colorFromFrameGraphics(SkinFrameElements frame) const; @@ -455,6 +543,16 @@ public: //so that theme graphic background can be drawn. static bool canDrawThemeBackground(const QBrush &backgroundBrush); + static int currentAnimationFrame(QS60StyleEnums::SkinParts part); +#ifdef Q_WS_S60 + + //No support for animations on emulated style + void startAnimation(QS60StyleEnums::SkinParts animation); + void stopAnimation(QS60StyleEnums::SkinParts animation); + static QS60StyleAnimation* animationDefinition(QS60StyleEnums::SkinParts part); + +#endif + private: static void drawPart(QS60StyleEnums::SkinParts part, QPainter *painter, const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); @@ -497,6 +595,12 @@ private: QPalette m_originalPalette; QPointer<QFocusFrame> m_focusFrame; + +#ifdef Q_WS_S60 + //list of progress bars having animation running + QList<QProgressBar *> m_bars; +#endif + }; QT_END_NAMESPACE diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index be61073..a3bb169 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -63,6 +63,7 @@ #include <aknutils.h> #include <aknnavi.h> #include <gulicon.h> +#include <AknBitmapAnimation.h> #if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) @@ -72,6 +73,7 @@ enum TDrawType { EDrawIcon, EDrawGulIcon, EDrawBackground, + EDrawAnimation, ENoDraw }; @@ -97,6 +99,47 @@ typedef struct { int newMinorSkinId; } partMapEntry; +AnimationData::AnimationData(const QS60StyleEnums::SkinParts part, int frames, int interval) : m_id(part), + m_frames(frames), m_interval(interval), m_mode(QS60StyleEnums::AM_Looping) +{ +} + +AnimationDataV2::AnimationDataV2(const AnimationData &data) : AnimationData(data.m_id, data.m_frames, data.m_interval), + m_resourceBased(false), m_animation(0), m_timerId(0) +{ +} +AnimationDataV2::~AnimationDataV2() +{ + delete m_animation; +} + +QS60StyleAnimation::QS60StyleAnimation(const QS60StyleEnums::SkinParts part, int frames, int interval) +{ + QT_TRAP_THROWING(m_defaultData = new (ELeave) AnimationData(part, frames, interval)); + QT_TRAP_THROWING(m_currentData = new (ELeave) AnimationDataV2(*m_defaultData)); +} + +QS60StyleAnimation::~QS60StyleAnimation() +{ + delete m_currentData; + delete m_defaultData; +} + +void QS60StyleAnimation::setAnimationObject(CAknBitmapAnimation* animation) +{ + Q_ASSERT(animation); + if (m_currentData->m_animation) + delete m_currentData->m_animation; + m_currentData->m_animation = animation; +} + +void QS60StyleAnimation::resetToDefaults() +{ + delete m_currentData; + m_currentData = 0; + QT_TRAP_THROWING(m_currentData = new (ELeave) AnimationDataV2(*m_defaultData)); +} + class QS60StyleModeSpecifics { public: @@ -113,6 +156,8 @@ public: static QSize naviPaneSize(); static TAknsItemID partSpecificThemeId(int part); + static QVariant themeDefinition(QS60StyleEnums::ThemeDefinitions definition, QS60StyleEnums::SkinParts part); + private: static QPixmap createSkinnedGraphicsLX(QS60StyleEnums::SkinParts part, const QSize &size, QS60StylePrivate::SkinElementFlags flags); @@ -128,7 +173,7 @@ private: }; const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { - /* SP_QgnGrafBarWait */ {KAknsIIDQgnGrafBarWaitAnim, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnGrafBarWaitAnim */ {KAknsIIDQgnGrafBarWaitAnim, EDrawAnimation, ES60_All, -1,-1}, /* SP_QgnGrafBarFrameCenter */ {KAknsIIDQgnGrafBarFrameCenter, EDrawIcon, ES60_All, -1,-1}, /* SP_QgnGrafBarFrameSideL */ {KAknsIIDQgnGrafBarFrameSideL, EDrawIcon, ES60_All, -1,-1}, /* SP_QgnGrafBarFrameSideR */ {KAknsIIDQgnGrafBarFrameSideR, EDrawIcon, ES60_All, -1,-1}, @@ -371,7 +416,7 @@ QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics( void QS60StyleModeSpecifics::fallbackInfo(const QS60StyleEnums::SkinParts &stylePart, TInt &fallbackIndex) { switch(stylePart) { - case QS60StyleEnums::SP_QgnGrafBarWait: + case QS60StyleEnums::SP_QgnGrafBarWaitAnim: fallbackIndex = EMbmAvkonQgn_graf_bar_wait_1; break; case QS60StyleEnums::SP_QgnGrafBarFrameCenter: @@ -604,6 +649,11 @@ bool QS60StylePrivate::hasSliderGrooveGraphic() return QSysInfo::s60Version() != QSysInfo::SV_S60_3_1; } +bool QS60StylePrivate::isSingleClickUi() +{ + return (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0); +} + QPoint qt_s60_fill_background_offset(const QWidget *targetWidget) { CCoeControl *control = targetWidget->effectiveWinId(); @@ -709,6 +759,69 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( // QS60WindowSurface::lockBitmapHeap(); break; } + case EDrawAnimation: { + CFbsBitmap* animationFrame; + CFbsBitmap* frameMask; + CAknBitmapAnimation* aknAnimation = 0; + TBool constructedFromTheme = ETrue; + + QS60StyleAnimation* animation = QS60StylePrivate::animationDefinition(part); //ownership is not passed + if (animation) { + if (!animation->animationObject() && !animation->isResourceBased()) {// no pre-made item exists, create new animation + CAknBitmapAnimation* newAnimation = CAknBitmapAnimation::NewL(); + CleanupStack::PushL(newAnimation); + if (newAnimation) + constructedFromTheme = newAnimation->ConstructFromSkinL(skinId); + if (constructedFromTheme && newAnimation->BitmapAnimData()->FrameArray().Count() > 0) { + animation->setResourceBased(false); + animation->setAnimationObject(newAnimation); //animation takes ownership + } + CleanupStack::Pop(newAnimation); + } + //fill-in stored information + aknAnimation = animation->animationObject(); + constructedFromTheme = !animation->isResourceBased(); + } + + const int currentFrame = QS60StylePrivate::currentAnimationFrame(part); + if (constructedFromTheme && aknAnimation && aknAnimation->BitmapAnimData()->FrameArray().Count() > 0) { + //Animation was created succesfully and contains frames, just fetch current frame + if(currentFrame >= aknAnimation->BitmapAnimData()->FrameArray().Count()) + User::Leave(KErrOverflow); + const CBitmapFrameData* frameData = aknAnimation->BitmapAnimData()->FrameArray().At(currentFrame); + if (frameData) { + animationFrame = frameData->Bitmap(); + frameMask = frameData->Mask(); + } + } else { + //Theme does not contain animation theming, create frames from resource file + TInt fallbackGraphicID = -1; + fallbackInfo(part, fallbackGraphicID); + fallbackGraphicID = fallbackGraphicID + (currentFrame * 2); //skip masks + TInt fallbackGraphicsMaskID = + (fallbackGraphicID == KErrNotFound) ? KErrNotFound : fallbackGraphicID + 1; //masks are auto-generated as next in mif files + if (fallbackGraphicsMaskID != KErrNotFound) + fallbackGraphicsMaskID = fallbackGraphicsMaskID + (currentFrame * 2); //skip actual graphics + + //Then draw animation frame + AknsUtils::CreateIconL( + skinInstance, + KAknsIIDDefault, //animation is not themed, lets force fallback graphics + animationFrame, + frameMask, + AknIconUtils::AvkonIconFileName(), + fallbackGraphicID , + fallbackGraphicsMaskID); + } + result = fromFbsBitmap(animationFrame, frameMask, flags, targetSize); + if (!constructedFromTheme) { + delete animationFrame; + animationFrame = 0; + delete frameMask; + frameMask = 0; + } + break; + } } if (!result) result = QPixmap(); @@ -731,7 +844,6 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFr MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); QPixmap result; -// QS60WindowSurface::unlockBitmapHeap(); static const TDisplayMode displayMode = S60->supportsPremultipliedAlpha ? Q_SYMBIAN_ECOLOR16MAP : EColor16MA; static const TInt drawParam = S60->supportsPremultipliedAlpha ? KAknsDrawParamDefault : KAknsDrawParamNoClearUnderImage|KAknsDrawParamRGBOnly; @@ -985,8 +1097,13 @@ void QS60StylePrivate::setActiveLayout() m_pmPointer = data[activeLayoutIndex]; } +Q_GLOBAL_STATIC(QList<QS60StyleAnimation *>, m_animations) + QS60StylePrivate::QS60StylePrivate() { + //Animation defaults need to be created when style is instantiated + QS60StyleAnimation* progressBarAnimation = new QS60StyleAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim, 7, 100); + m_animations()->append(progressBarAnimation); // No need to set active layout, if dynamic metrics API is available setActiveLayout(); } @@ -1187,6 +1304,11 @@ void QS60StylePrivate::handleSkinChange() setThemePalette(topLevelWidget); topLevelWidget->ensurePolished(); } +#ifndef QT_NO_PROGRESSBAR + //re-start animation timer + stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); //todo: once we have more animations, we could say "stop all running ones" + startAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); //and "re-start all previously running ones" +#endif } QSize QS60StylePrivate::naviPaneSize() @@ -1206,6 +1328,121 @@ QSize QS60StyleModeSpecifics::naviPaneSize() return QSize(0,0); } +int QS60StylePrivate::currentAnimationFrame(QS60StyleEnums::SkinParts part) +{ + QS60StyleAnimation *animation = animationDefinition(part); + // todo: looping could be done in QS60Style::timerEvent + if (animation->frameCount() == animation->currentFrame()) + animation->setCurrentFrame(0); + return animation->currentFrame(); +} + +QS60StyleAnimation* QS60StylePrivate::animationDefinition(QS60StyleEnums::SkinParts part) +{ + int i = 0; + const int animationsCount = m_animations()->isEmpty() ? 0 : m_animations()->count(); + for(; i < animationsCount; i++) { + if (part == m_animations()->at(i)->animationId()) + break; + } + return m_animations()->at(i); +} + +void QS60StylePrivate::startAnimation(QS60StyleEnums::SkinParts animationPart) +{ + Q_Q(QS60Style); + + //Query animation data from theme and store values to local struct. + QVariant themeAnimationDataVariant = QS60StyleModeSpecifics::themeDefinition( + QS60StyleEnums::TD_AnimationData, animationPart); + QList<QVariant> themeAnimationData = themeAnimationDataVariant.toList(); + + QS60StyleAnimation *animation = QS60StylePrivate::animationDefinition(animationPart); + if (animation) { + if (themeAnimationData.at(QS60StyleEnums::AD_Interval).toInt() != 0) + animation->setInterval(themeAnimationData.at(QS60StyleEnums::AD_Interval).toInt()); + + if (themeAnimationData.at(QS60StyleEnums::AD_NumberOfFrames).toInt() != 0) + animation->setFrameCount(themeAnimationData.at(QS60StyleEnums::AD_NumberOfFrames).toInt()); + + //todo: playmode is ignored for now, since it seems to return invalid data on some themes + //lets use the table values for play mode + + animation->setCurrentFrame(0); //always initialize + const int timerId = q->startTimer(animation->interval()); + animation->setTimerId(timerId); + } +} + +void QS60StylePrivate::stopAnimation(QS60StyleEnums::SkinParts animationPart) +{ + Q_Q(QS60Style); + + QS60StyleAnimation *animation = QS60StylePrivate::animationDefinition(animationPart); + if (animation) { + animation->setCurrentFrame(0); + if (animation->timerId() != 0) { + q->killTimer(animation->timerId()); + animation->setTimerId(0); + } + animation->resetToDefaults(); + } +} + +QVariant QS60StyleModeSpecifics::themeDefinition( + QS60StyleEnums::ThemeDefinitions definition, QS60StyleEnums::SkinParts part) +{ + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + + Q_ASSERT(skinInstance); + + switch(definition) { + //Animation definitions + case QS60StyleEnums::TD_AnimationData: + { + CAknsBmpAnimItemData *animationData; + TAknsItemID animationSkinId = partSpecificThemeId(part); + QList<QVariant> list; + + TRAPD( error, QT_TRYCATCH_LEAVING( + animationData = static_cast<CAknsBmpAnimItemData*>(skinInstance->CreateUncachedItemDataL( + animationSkinId, EAknsITBmpAnim)))); + if (error) + return list; + + if (animationData) { + list.append((int)animationData->FrameInterval()); + list.append((int)animationData->NumberOfImages()); + + QS60StyleEnums::AnimationMode playMode; + switch(animationData->PlayMode()) { + case CBitmapAnimClientData::EPlay: + playMode = QS60StyleEnums::AM_PlayOnce; + break; + case CBitmapAnimClientData::ECycle: + playMode = QS60StyleEnums::AM_Looping; + break; + case CBitmapAnimClientData::EBounce: + playMode = QS60StyleEnums::AM_Bounce; + break; + default: + break; + } + list.append(QVariant((int)playMode)); + delete animationData; + } else { + list.append(0); + list.append(0); + } + return list; + } + break; + default: + break; + } + return QVariant(); +} + #endif // Q_WS_S60 QT_END_NAMESPACE diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp index bd43eb7..f87cf28 100644 --- a/src/gui/styles/qs60style_simulated.cpp +++ b/src/gui/styles/qs60style_simulated.cpp @@ -342,6 +342,11 @@ bool QS60StylePrivate::hasSliderGrooveGraphic() return false; } +bool QS60StylePrivate::isSingleClickUi() +{ + return false; +} + QFont QS60StylePrivate::s60Font_specific( QS60StyleEnums::FontCategories fontCategory, int pointSize, bool resolveFontSize) @@ -364,6 +369,11 @@ QFont QS60StylePrivate::s60Font_specific( return result; } +int QS60StylePrivate::currentAnimationFrame(QS60StyleEnums::SkinParts part) +{ + return 0; +} + /*! Constructs a QS60Style object. */ diff --git a/src/gui/styles/qstyle_s60.qrc b/src/gui/styles/qstyle_s60.qrc new file mode 100644 index 0000000..dbee38b --- /dev/null +++ b/src/gui/styles/qstyle_s60.qrc @@ -0,0 +1,137 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/trolltech/styles/commonstyle"> +<!-- <file>images/filelink-16.png</file> --> +<file>images/filelink-32.png</file> +<!-- <file>images/filelink-128.png</file> --> +<!-- <file>images/file-16.png</file> --> +<file>images/file-32.png</file> +<!-- <file>images/file-128.png</file> --> +<!-- <file>images/newdirectory-16.png</file> --> +<file>images/newdirectory-32.png</file> +<!-- <file>images/newdirectory-128.png</file> --> +<!-- <file>images/parentdir-16.png</file> --> +<file>images/parentdir-32.png</file> +<!-- <file>images/parentdir-128.png</file> --> +<!-- <file>images/dvd-16.png</file> --> +<!-- <file>images/dvd-32.png</file> --> +<!-- <file>images/dvd-128.png</file> --> +<!-- <file>images/cdr-16.png</file> --> +<!-- <file>images/cdr-32.png</file> --> +<!-- <file>images/cdr-128.png</file> --> +<!-- <file>images/floppy-16.png</file> --> +<!-- <file>images/floppy-32.png</file> --> +<!-- <file>images/floppy-128.png</file> --> +<!-- <file>images/harddrive-16.png</file> --> +<file>images/harddrive-32.png</file> +<!-- <file>images/harddrive-128.png</file> --> +<!-- <file>images/trash-16.png</file> --> +<!-- <file>images/trash-32.png</file> --> +<!-- <file>images/trash-128.png</file> --> +<!-- <file>images/networkdrive-16.png</file> --> +<!-- <file>images/networkdrive-32.png</file> --> +<!-- <file>images/networkdrive-128.png</file> --> +<!-- <file>images/computer-16.png</file> --> +<!-- <file>images/computer-32.png</file> --> +<!-- <file>images/desktop-16.png</file> --> +<file>images/desktop-32.png</file> +<!-- <file>images/dirclosed-16.png</file> --> +<file>images/dirclosed-32.png</file> +<!-- <file>images/dirclosed-128.png</file> --> +<!-- <file>images/dirlink-16.png</file> --> +<file>images/dirlink-32.png</file> +<!-- <file>images/dirlink-128.png</file> --> +<!-- <file>images/diropen-16.png</file> --> +<file>images/diropen-32.png</file> +<!-- <file>images/diropen-128.png</file> --> +<!-- <file>images/left-16.png</file> --> +<file>images/left-32.png</file> +<!-- <file>images/left-128.png</file> --> +<!-- <file>images/right-16.png</file> --> +<file>images/right-32.png</file> +<!-- <file>images/right-128.png</file> --> +<!-- <file>images/up-16.png</file> --> +<file>images/up-32.png</file> +<!-- <file>images/up-128.png</file> --> +<!-- <file>images/down-16.png</file> --> +<file>images/down-32.png</file> +<!-- <file>images/down-128.png</file> --> +<!-- <file>images/filecontents-16.png</file> --> +<file>images/filecontents-32.png</file> +<!-- <file>images/filecontents-128.png</file> --> +<!-- <file>images/fileinfo-16.png</file> --> +<file>images/fileinfo-32.png</file> +<!-- <file>images/fileinfo-128.png</file> --> +<!-- <file>images/viewdetailed-16.png</file> --> +<file>images/viewdetailed-32.png</file> +<!-- <file>images/viewdetailed-128.png</file> --> +<!-- <file>images/viewlist-16.png</file> --> +<file>images/viewlist-32.png</file> +<!-- <file>images/viewlist-128.png</file> --> +<file>images/fontbitmap-16.png</file> +<file>images/fonttruetype-16.png</file> +<!-- <file>images/standardbutton-apply-128.png</file> --> +<!-- <file>images/standardbutton-apply-16.png</file> --> +<file>images/standardbutton-apply-32.png</file> +<!-- <file>images/standardbutton-cancel-128.png</file> --> +<!-- <file>images/standardbutton-cancel-16.png</file> --> +<file>images/standardbutton-cancel-32.png</file> +<!-- <file>images/standardbutton-clear-128.png</file> --> +<!-- <file>images/standardbutton-clear-16.png</file> --> +<file>images/standardbutton-clear-32.png</file> +<!-- <file>images/standardbutton-close-128.png</file> --> +<!-- <file>images/standardbutton-close-16.png</file> --> +<file>images/standardbutton-close-32.png</file> +<!-- <file>images/standardbutton-delete-128.png</file> --> +<!-- <file>images/standardbutton-delete-16.png</file> --> +<file>images/standardbutton-delete-32.png</file> +<!-- <file>images/standardbutton-help-128.png</file> --> +<!-- <file>images/standardbutton-help-16.png</file> --> +<file>images/standardbutton-help-32.png</file> +<!-- <file>images/standardbutton-no-128.png</file> --> +<!-- <file>images/standardbutton-no-16.png</file> --> +<file>images/standardbutton-no-32.png</file> +<!-- <file>images/standardbutton-ok-128.png</file> --> +<!-- <file>images/standardbutton-ok-16.png</file> --> +<file>images/standardbutton-ok-32.png</file> +<!-- <file>images/standardbutton-open-128.png</file> --> +<!-- <file>images/standardbutton-open-16.png</file> --> +<file>images/standardbutton-open-32.png</file> +<!-- <file>images/standardbutton-save-128.png</file> --> +<!-- <file>images/standardbutton-save-16.png</file> --> +<file>images/standardbutton-save-32.png</file> +<!-- <file>images/standardbutton-yes-128.png</file> --> +<!-- <file>images/standardbutton-yes-16.png</file> --> +<file>images/standardbutton-yes-32.png</file> +<file>images/standardbutton-closetab-16.png</file> +<file>images/standardbutton-closetab-down-16.png</file> +<file>images/standardbutton-closetab-hover-16.png</file> +<!-- <file>images/refresh-24.png</file> --> +<file>images/refresh-32.png</file> +<!-- <file>images/stop-24.png</file> --> +<file>images/stop-32.png</file> +<!-- <file>images/media-stop-16.png</file> --> +<file>images/media-stop-32.png</file> +<!-- <file>images/media-play-16.png</file> --> +<file>images/media-play-32.png</file> +<!-- <file>images/media-pause-16.png</file> --> +<file>images/media-pause-32.png</file> +<!-- <file>images/media-seek-forward-16.png</file> --> +<file>images/media-seek-forward-32.png</file> +<!-- <file>images/media-seek-backward-16.png</file> --> +<file>images/media-seek-backward-32.png</file> +<!-- <file>images/media-skip-forward-16.png</file> --> +<file>images/media-skip-forward-32.png</file> +<!-- <file>images/media-skip-backward-16.png</file> --> +<file>images/media-skip-backward-32.png</file> +<file>images/media-volume-16.png</file> +<file>images/media-volume-muted-16.png</file> +</qresource> +<!-- +<qresource prefix="/trolltech/styles/macstyle"> +<file>images/closedock-16.png</file> +<file>images/closedock-down-16.png</file> +<file>images/dockdock-16.png</file> +<file>images/dockdock-down-16.png</file> +</qresource> +--> +</RCC> diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index 7e5c55a..676f59e 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -23,10 +23,12 @@ SOURCES += \ styles/qstylesheetstyle.cpp \ styles/qstylesheetstyle_default.cpp -!wince* { - RESOURCES += styles/qstyle.qrc +wince* { + RESOURCES += styles/qstyle_wince.qrc +} else:symbian { + RESOURCES += styles/qstyle_s60.qrc } else { - RESOURCES += styles/qstyle_wince.qrc + RESOURCES += styles/qstyle.qrc } contains( styles, all ) { @@ -168,7 +170,7 @@ contains( styles, s60 ):contains(QT_CONFIG, s60) { SOURCES += styles/qs60style.cpp symbian { SOURCES += styles/qs60style_s60.cpp - LIBS += -laknicon -laknskins -laknskinsrv -lfontutils -legul + LIBS += -laknicon -laknskins -laknskinsrv -lfontutils -legul -lbmpanim } else { SOURCES += styles/qs60style_simulated.cpp RESOURCES += styles/qstyle_s60_simulated.qrc diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 13e67e9..4a6235c 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -66,7 +66,7 @@ #endif #if defined(Q_OS_SYMBIAN) -#include <W32STD.H> +#include <w32std.h> #include <private/qt_s60_p.h> #endif diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 070091a..b0a64ea 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -510,10 +510,12 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); } else { // mask selection - o.start = m_cursor; - o.length = 1; - o.format.setBackground(m_palette.brush(QPalette::Text)); - o.format.setForeground(m_palette.brush(QPalette::Window)); + if(!m_blinkPeriod || m_blinkStatus){ + o.start = m_cursor; + o.length = 1; + o.format.setBackground(m_palette.brush(QPalette::Text)); + o.format.setForeground(m_palette.brush(QPalette::Window)); + } } selections.append(o); } @@ -522,8 +524,11 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl m_textLayout.draw(painter, offset, selections, clip); if (flags & DrawCursor){ + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; if(!m_blinkPeriod || m_blinkStatus) - m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth); } } diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 301ff72..d6f2705 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -549,7 +549,10 @@ inline qreal QLineControl::cursorToX(int cursor) const inline qreal QLineControl::cursorToX() const { - return cursorToX(m_cursor); + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; + return cursorToX(cursor); } inline bool QLineControl::isReadOnly() const diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index e41c2be..ee79f5a 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -476,6 +476,17 @@ void QMainWindowLayout::cleanUpMacToolbarItems() CFRelease(toolbarItemsCopy.at(i)); toolbarItemsCopy.clear(); unifiedToolbarHash.clear(); + +#ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + + OSWindowRef window = qt_mac_window_for(layoutState.mainWindow); + NSToolbar *macToolbar = [window toolbar]; + if (macToolbar) { + [[macToolbar delegate] release]; + [macToolbar setDelegate:nil]; + } +#endif } void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp index 396e233..2509a21 100644 --- a/src/gui/widgets/qstackedwidget.cpp +++ b/src/gui/widgets/qstackedwidget.cpp @@ -186,8 +186,11 @@ int QStackedWidget::insertWidget(int index, QWidget *widget) } /*! - Removes the given \a widget from the QStackedWidget. The widget - is \e not deleted. + Removes the given \a widget from the QStackedWidget. + + \bold{Note:} The ownership of \a widget remains the same. + The widget is \e not deleted, but simply removed from the widget's + stacked layout, causing it to be hidden. \sa addWidget(), insertWidget(), currentWidget() */ diff --git a/src/multimedia/audio/qaudio_mac.cpp b/src/multimedia/audio/qaudio_mac.cpp index 61a00ce..14fee8b 100644 --- a/src/multimedia/audio/qaudio_mac.cpp +++ b/src/multimedia/audio/qaudio_mac.cpp @@ -48,8 +48,8 @@ QT_BEGIN_NAMESPACE QDebug operator<<(QDebug dbg, const QAudioFormat& audioFormat) { dbg.nospace() << "QAudioFormat(" << - audioFormat.sampleRate() << "," << - audioFormat.channelCount() << "," << + audioFormat.frequency() << "," << + audioFormat.channels() << "," << audioFormat.sampleSize()<< "," << audioFormat.codec() << "," << audioFormat.byteOrder() << "," << @@ -64,8 +64,8 @@ QAudioFormat toQAudioFormat(AudioStreamBasicDescription const& sf) { QAudioFormat audioFormat; - audioFormat.setSampleRate(sf.mSampleRate); - audioFormat.setChannelCount(sf.mChannelsPerFrame); + audioFormat.setFrequency(sf.mSampleRate); + audioFormat.setChannels(sf.mChannelsPerFrame); audioFormat.setSampleSize(sf.mBitsPerChannel); audioFormat.setCodec(QString::fromLatin1("audio/pcm")); audioFormat.setByteOrder(sf.mFormatFlags & kLinearPCMFormatFlagIsBigEndian != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian); @@ -84,9 +84,9 @@ AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& au AudioStreamBasicDescription sf; sf.mFormatFlags = kAudioFormatFlagIsPacked; - sf.mSampleRate = audioFormat.sampleRate(); + sf.mSampleRate = audioFormat.frequency(); sf.mFramesPerPacket = 1; - sf.mChannelsPerFrame = audioFormat.channelCount(); + sf.mChannelsPerFrame = audioFormat.channels(); sf.mBitsPerChannel = audioFormat.sampleSize(); sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8); sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame; diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp index ca20eda..092efc5 100644 --- a/src/multimedia/audio/qaudiodeviceinfo.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo.cpp @@ -100,13 +100,13 @@ public: You can also query each device for the formats it supports. A format in this context is a set consisting of a specific byte - order, channel, codec, sample rate, sample size and sample type. A + order, channel, codec, frequency, sample rate, and sample type. A format is represented by the QAudioFormat class. The values supported by the the device for each of these parameters can be fetched with supportedByteOrders(), supportedChannels(), supportedCodecs(), - supportedSampleRates(), supportedSampleSizes(), and + supportedFrequencies(), supportedSampleSizes(), and supportedSampleTypes(). The combinations supported are dependent on the platform, audio plugins installed and the audio device capabilities. If you need a specific format, you can check if the device supports it with isFormatSupported(), or fetch a @@ -259,16 +259,7 @@ QStringList QAudioDeviceInfo::supportedCodecs() const } /*! - Returns a list of supported sample rates. -*/ - -QList<int> QAudioDeviceInfo::supportedSampleRates() const -{ - return supportedFrequencies(); -} - -/*! - \internal + Returns a list of supported frequencies. */ QList<int> QAudioDeviceInfo::supportedFrequencies() const @@ -277,16 +268,7 @@ QList<int> QAudioDeviceInfo::supportedFrequencies() const } /*! - Returns a list of supported channel counts. -*/ - -QList<int> QAudioDeviceInfo::supportedChannelCounts() const -{ - return supportedChannels(); -} - -/*! - \internal + Returns a list of supported channels. */ QList<int> QAudioDeviceInfo::supportedChannels() const diff --git a/src/multimedia/audio/qaudiodeviceinfo.h b/src/multimedia/audio/qaudiodeviceinfo.h index 1cc0731..62dc8a2 100644 --- a/src/multimedia/audio/qaudiodeviceinfo.h +++ b/src/multimedia/audio/qaudiodeviceinfo.h @@ -84,9 +84,7 @@ public: QStringList supportedCodecs() const; QList<int> supportedFrequencies() const; - QList<int> supportedSampleRates() const; QList<int> supportedChannels() const; - QList<int> supportedChannelCounts() const; QList<int> supportedSampleSizes() const; QList<QAudioFormat::Endian> supportedByteOrders() const; QList<QAudioFormat::SampleType> supportedSampleTypes() const; diff --git a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp index a77a428..36270a7 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp @@ -78,20 +78,20 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const { QAudioFormat nearest; if(mode == QAudio::AudioOutput) { - nearest.setSampleRate(44100); - nearest.setChannelCount(2); + nearest.setFrequency(44100); + nearest.setChannels(2); nearest.setByteOrder(QAudioFormat::LittleEndian); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(16); nearest.setCodec(QLatin1String("audio/pcm")); } else { - nearest.setSampleRate(8000); - nearest.setChannelCount(1); + nearest.setFrequency(8000); + nearest.setChannels(1); nearest.setSampleType(QAudioFormat::UnSignedInt); nearest.setSampleSize(8); nearest.setCodec(QLatin1String("audio/pcm")); if(!testSettings(nearest)) { - nearest.setChannelCount(2); + nearest.setChannels(2); nearest.setSampleSize(16); nearest.setSampleType(QAudioFormat::SignedInt); } @@ -253,8 +253,8 @@ bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const snd_pcm_hw_params_any( handle, params ); // set the values! - snd_pcm_hw_params_set_channels(handle,params,format.channelCount()); - snd_pcm_hw_params_set_rate(handle,params,format.sampleRate(),dir); + snd_pcm_hw_params_set_channels(handle,params,format.channels()); + snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) @@ -295,18 +295,18 @@ bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const } else testCodec = true; - if(err>=0 && format.channelCount() != -1) { - err = snd_pcm_hw_params_test_channels(handle,params,format.channelCount()); + if(err>=0 && format.channels() != -1) { + err = snd_pcm_hw_params_test_channels(handle,params,format.channels()); if(err>=0) - err = snd_pcm_hw_params_set_channels(handle,params,format.channelCount()); + err = snd_pcm_hw_params_set_channels(handle,params,format.channels()); if(err>=0) testChannel = true; } - if(err>=0 && format.sampleRate() != -1) { - err = snd_pcm_hw_params_test_rate(handle,params,format.sampleRate(),0); + if(err>=0 && format.frequency() != -1) { + err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0); if(err>=0) - err = snd_pcm_hw_params_set_rate(handle,params,format.sampleRate(),dir); + err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); if(err>=0) testFreq = true; } diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp index 9334069..ecd03e5 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp @@ -144,10 +144,10 @@ QAudioFormat QAudioDeviceInfoInternal::nearestFormat(const QAudioFormat& format) rc.setCodec(QString::fromLatin1("audio/pcm")); - if (rc.sampleRate() != target.sampleRate()) - rc.setSampleRate(target.sampleRate()); - if (rc.channelCount() != target.channelCount()) - rc.setChannelCount(target.channelCount()); + if (rc.frequency() != target.frequency()) + rc.setFrequency(target.frequency()); + if (rc.channels() != target.channels()) + rc.setChannels(target.channels()); if (rc.sampleSize() != target.sampleSize()) rc.setSampleSize(target.sampleSize()); if (rc.byteOrder() != target.byteOrder()) diff --git a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp index 373e23d..f6b8154 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp @@ -94,15 +94,15 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const { QAudioFormat nearest; if(mode == QAudio::AudioOutput) { - nearest.setSampleRate(44100); - nearest.setChannelCount(2); + nearest.setFrequency(44100); + nearest.setChannels(2); nearest.setByteOrder(QAudioFormat::LittleEndian); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(16); nearest.setCodec(QLatin1String("audio/pcm")); } else { - nearest.setSampleRate(11025); - nearest.setChannelCount(1); + nearest.setFrequency(11025); + nearest.setChannels(1); nearest.setByteOrder(QAudioFormat::LittleEndian); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(8); @@ -181,12 +181,12 @@ bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const if(!format.codec().startsWith(QLatin1String("audio/pcm"))) failed = true; - if(!failed && !(format.channelCount() == 1 || format.channelCount() == 2)) + if(!failed && !(format.channels() == 1 || format.channels() == 2)) failed = true; if(!failed) { - if(!(format.sampleRate() == 8000 || format.sampleRate() == 11025 || format.sampleRate() == 22050 || - format.sampleRate() == 44100 || format.sampleRate() == 48000 || format.sampleRate() == 96000)) + if(!(format.frequency() == 8000 || format.frequency() == 11025 || format.frequency() == 22050 || + format.frequency() == 44100 || format.frequency() == 48000 || format.frequency() == 96000)) failed = true; } diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp index 58bb571..89ae0ff 100644 --- a/src/multimedia/audio/qaudioformat.cpp +++ b/src/multimedia/audio/qaudioformat.cpp @@ -144,7 +144,7 @@ public: Values are initialized as follows: \list \o frequency() = -1 - \o channelCount() = -1 + \o channels() = -1 \o sampleSize() = -1 \o byteOrder() = QAudioFormat::Endian(QSysInfo::ByteOrder) \o sampleType() = QAudioFormat::Unknown @@ -224,16 +224,7 @@ bool QAudioFormat::isValid() const } /*! - Sets the sample rate to \a samplerate Hertz. -*/ - -void QAudioFormat::setSampleRate(int samplerate) -{ - d->frequency = samplerate; -} - -/*! - \internal + Sets the frequency to \a frequency. */ void QAudioFormat::setFrequency(int frequency) @@ -242,16 +233,7 @@ void QAudioFormat::setFrequency(int frequency) } /*! - Returns the current sample rate in Hertz. -*/ - -int QAudioFormat::sampleRate() const -{ - return d->frequency; -} - -/*! - \internal + Returns the current frequency value. */ int QAudioFormat::frequency() const @@ -260,16 +242,7 @@ int QAudioFormat::frequency() const } /*! - Sets the channel count to \a channels. -*/ - -void QAudioFormat::setChannelCount(int channels) -{ - d->channels = channels; -} - -/*! - \internal + Sets the channels to \a channels. */ void QAudioFormat::setChannels(int channels) @@ -278,16 +251,7 @@ void QAudioFormat::setChannels(int channels) } /*! - Returns the current channel count value. -*/ - -int QAudioFormat::channelCount() const -{ - return d->channels; -} - -/*! - \internal + Returns the current channel value. */ int QAudioFormat::channels() const diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h index b255907..cb58d1c 100644 --- a/src/multimedia/audio/qaudioformat.h +++ b/src/multimedia/audio/qaudioformat.h @@ -76,12 +76,6 @@ public: void setFrequency(int frequency); int frequency() const; - void setSampleRate(int samplerate); - int sampleRate() const; - - void setChannelCount(int channels); - int channelCount() const; - void setChannels(int channels); int channels() const; diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index da39c4a..45cafc1 100644 --- a/src/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/audio/qaudioinput.cpp @@ -88,8 +88,8 @@ QT_BEGIN_NAMESPACE QAudioFormat format; // set up the format you want, eg. - format.setSampleRate(8000); - format.setChannelCount(1); + format.setFrequency(8000); + format.setChannels(1); format.setSampleSize(8); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp index ea68c8d6..26e46b3 100644 --- a/src/multimedia/audio/qaudioinput_alsa_p.cpp +++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp @@ -256,7 +256,7 @@ bool QAudioInputPrivate::open() int dir; int err=-1; int count=0; - unsigned int freakuency=settings.sampleRate(); + unsigned int freakuency=settings.frequency(); QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput); @@ -332,7 +332,7 @@ bool QAudioInputPrivate::open() } } if ( !fatal ) { - err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channelCount() ); + err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err); @@ -505,7 +505,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) errorState = QAudio::NoError; deviceState = QAudio::IdleState; } else { - totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.sampleRate(); + totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency(); resuming = false; errorState = QAudio::NoError; deviceState = QAudio::ActiveState; @@ -702,7 +702,7 @@ qint64 InputPrivate::readData( char* data, qint64 len) count++; } if(err > 0 && readFrames > 0) { - audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.sampleRate()*1000; + audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000; audioDevice->deviceState = QAudio::ActiveState; return err; } diff --git a/src/multimedia/audio/qaudioinput_mac_p.cpp b/src/multimedia/audio/qaudioinput_mac_p.cpp index f5be8ee..7251513 100644 --- a/src/multimedia/audio/qaudioinput_mac_p.cpp +++ b/src/multimedia/audio/qaudioinput_mac_p.cpp @@ -814,7 +814,7 @@ int QAudioInputPrivate::notifyInterval() const qint64 QAudioInputPrivate::processedUSecs() const { - return totalFrames * 1000000 / audioFormat.sampleRate(); + return totalFrames * 1000000 / audioFormat.frequency(); } qint64 QAudioInputPrivate::elapsedUSecs() const diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index 5c597ef..17e8bfb 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -225,16 +225,16 @@ bool QAudioInputPrivate::open() header = 0; if(buffer_size == 0) { // Default buffer size, 100ms, default period size is 20ms - buffer_size = settings.sampleRate()*settings.channelCount()*(settings.sampleSize()/8)*0.1; + buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.1; period_size = buffer_size/5; } else { period_size = buffer_size/5; } timeStamp.restart(); elapsedTimeOffset = 0; - wfx.nSamplesPerSec = settings.sampleRate(); + wfx.nSamplesPerSec = settings.frequency(); wfx.wBitsPerSample = settings.sampleSize(); - wfx.nChannels = settings.channelCount(); + wfx.nChannels = settings.channels(); wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_PCM; @@ -374,8 +374,8 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) } else { totalTimeValue += waveBlocks[header].dwBytesRecorded - /((settings.channelCount()*settings.sampleSize()/8)) - *10000/settings.sampleRate()*100; + /((settings.channels()*settings.sampleSize()/8)) + *10000/settings.frequency()*100; errorState = QAudio::NoError; deviceState = QAudio::ActiveState; resuming = false; @@ -388,8 +388,8 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l; #endif totalTimeValue += waveBlocks[header].dwBytesRecorded - /((settings.channelCount()*settings.sampleSize()/8)) - *10000/settings.sampleRate()*100; + /((settings.channels()*settings.sampleSize()/8)) + *10000/settings.frequency()*100; errorState = QAudio::NoError; deviceState = QAudio::ActiveState; resuming = false; diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index b61aa4f..afd8a84 100644 --- a/src/multimedia/audio/qaudiooutput.cpp +++ b/src/multimedia/audio/qaudiooutput.cpp @@ -83,8 +83,8 @@ QT_BEGIN_NAMESPACE QAudioFormat format; // Set up the format, eg. - format.setSampleRate(8000); - format.setChannelCount(1); + format.setFrequency(8000); + format.setChannels(1); format.setSampleSize(8); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp index 43b65ec..7b89cef 100644 --- a/src/multimedia/audio/qaudiooutput_alsa_p.cpp +++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp @@ -279,7 +279,7 @@ bool QAudioOutputPrivate::open() int dir; int err=-1; int count=0; - unsigned int freakuency=settings.sampleRate(); + unsigned int freakuency=settings.frequency(); QString dev = QLatin1String(m_device.constData()); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); @@ -354,7 +354,7 @@ bool QAudioOutputPrivate::open() } } if ( !fatal ) { - err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channelCount() ); + err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err); @@ -494,7 +494,7 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) err = snd_pcm_writei( handle, data, frames ); } if(err > 0) { - totalTimeValue += err*1000000/settings.sampleRate(); + totalTimeValue += err*1000000/settings.frequency(); resuming = false; errorState = QAudio::NoError; deviceState = QAudio::ActiveState; diff --git a/src/multimedia/audio/qaudiooutput_mac_p.cpp b/src/multimedia/audio/qaudiooutput_mac_p.cpp index 4367ee7..518f78f 100644 --- a/src/multimedia/audio/qaudiooutput_mac_p.cpp +++ b/src/multimedia/audio/qaudiooutput_mac_p.cpp @@ -87,8 +87,8 @@ public: m_device(0) { m_buffer = new QAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize))); - m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channelCount(); - m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.sampleRate(); + m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channels(); + m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.frequency(); m_fillTimer = new QTimer(this); connect(m_fillTimer, SIGNAL(timeout()), SLOT(fillBuffer())); @@ -546,7 +546,7 @@ int QAudioOutputPrivate::notifyInterval() const qint64 QAudioOutputPrivate::processedUSecs() const { - return totalFrames * 1000000 / audioFormat.sampleRate(); + return totalFrames * 1000000 / audioFormat.frequency(); } qint64 QAudioOutputPrivate::elapsedUSecs() const diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index b6e9762..c31e048 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -213,7 +213,7 @@ bool QAudioOutputPrivate::open() #endif if(buffer_size == 0) { // Default buffer size, 200ms, default period size is 40ms - buffer_size = settings.sampleRate()*settings.channelCount()*(settings.sampleSize()/8)*0.2; + buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; period_size = buffer_size/5; } else { period_size = buffer_size/5; @@ -232,9 +232,9 @@ bool QAudioOutputPrivate::open() timeStamp.restart(); elapsedTimeOffset = 0; - wfx.nSamplesPerSec = settings.sampleRate(); + wfx.nSamplesPerSec = settings.frequency(); wfx.wBitsPerSample = settings.sampleSize(); - wfx.nChannels = settings.channelCount(); + wfx.nChannels = settings.channels(); wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_PCM; @@ -289,8 +289,8 @@ void QAudioOutputPrivate::close() return; deviceState = QAudio::StoppedState; - int delay = (buffer_size-bytesFree())*1000/(settings.sampleRate() - *settings.channelCount()*(settings.sampleSize()/8)); + int delay = (buffer_size-bytesFree())*1000/(settings.frequency() + *settings.channels()*(settings.sampleSize()/8)); waveOutReset(hWaveOut); Sleep(delay+10); @@ -386,8 +386,8 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) LeaveCriticalSection(&waveOutCriticalSection); #endif totalTimeValue += current->dwBufferLength - /(settings.channelCount()*(settings.sampleSize()/8)) - *1000000/settings.sampleRate();; + /(settings.channels()*(settings.sampleSize()/8)) + *1000000/settings.frequency();; waveCurrentBlock++; waveCurrentBlock %= buffer_size/period_size; current = &waveBlocks[waveCurrentBlock]; diff --git a/src/network/access/qfilenetworkreply.cpp b/src/network/access/qfilenetworkreply.cpp index 44dd9e7..8c5065c 100644 --- a/src/network/access/qfilenetworkreply.cpp +++ b/src/network/access/qfilenetworkreply.cpp @@ -44,35 +44,32 @@ #include "QtCore/qdatetime.h" #include <QtCore/QCoreApplication> #include <QtCore/QFileInfo> +#include <QDebug> QT_BEGIN_NAMESPACE QFileNetworkReplyPrivate::QFileNetworkReplyPrivate() - : QNetworkReplyPrivate(), realFileSize(0), finished(false) + : QNetworkReplyPrivate(), realFileSize(0) { } -QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req) +QFileNetworkReply::~QFileNetworkReply() +{ +} + +QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) : QNetworkReply(*new QFileNetworkReplyPrivate(), parent) { setRequest(req); setUrl(req.url()); - setOperation(QNetworkAccessManager::GetOperation); - QMetaObject::invokeMethod(this, "_q_startOperation", Qt::QueuedConnection); + setOperation(op); QNetworkReply::open(QIODevice::ReadOnly); -} -QFileNetworkReply::~QFileNetworkReply() -{ -} + qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); -// This code is mostly inspired by QNetworkAccessFileBackend -// We also use its translation context for error messages -void QFileNetworkReplyPrivate::_q_startOperation() -{ - Q_Q(QFileNetworkReply); + QFileNetworkReplyPrivate *d = (QFileNetworkReplyPrivate*) d_func(); - QUrl url = q->url(); + QUrl url = req.url(); if (url.host() == QLatin1String("localhost")) url.setHost(QString()); @@ -81,81 +78,75 @@ void QFileNetworkReplyPrivate::_q_startOperation() if (!url.host().isEmpty()) { // we handle only local files QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()); - q->setError(QNetworkReply::ProtocolInvalidOperationError, msg); - emit q->error(QNetworkReply::ProtocolInvalidOperationError); - doFinished(); + setError(QNetworkReply::ProtocolInvalidOperationError, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError)); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); return; } #endif if (url.path().isEmpty()) url.setPath(QLatin1String("/")); - q->setUrl(url); + setUrl(url); QString fileName = url.toLocalFile(); if (fileName.isEmpty()) { fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); } - realFile.setFileName(fileName); + d->realFile.setFileName(fileName); - QFileInfo fi(realFile); + QFileInfo fi(d->realFile); if (fi.isDir()) { QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); - q->setError(QNetworkReply::ContentOperationNotPermittedError, msg); - emit q->error(QNetworkReply::ContentOperationNotPermittedError); - doFinished(); + setError(QNetworkReply::ContentOperationNotPermittedError, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError)); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); return; } - bool opened = realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); // could we open the file? if (!opened) { QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") - .arg(realFile.fileName(), realFile.errorString()); + .arg(d->realFile.fileName(), d->realFile.errorString()); - if (realFile.exists()) { - q->setError(QNetworkReply::ContentAccessDenied, msg); - emit q->error(QNetworkReply::ContentAccessDenied); + if (d->realFile.exists()) { + setError(QNetworkReply::ContentAccessDenied, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied)); } else { - q->setError(QNetworkReply::ContentNotFoundError, msg); - emit q->error(QNetworkReply::ContentNotFoundError); + setError(QNetworkReply::ContentNotFoundError, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError)); } - doFinished(); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); return; } - realFileSize = fi.size(); - q->setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); - q->setHeader(QNetworkRequest::ContentLengthHeader, realFileSize); + d->realFileSize = fi.size(); + setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); + setHeader(QNetworkRequest::ContentLengthHeader, d->realFileSize); - emit q->metaDataChanged(); - emit q->downloadProgress(realFileSize, realFileSize); - emit q->readyRead(); - doFinished(); + QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, + Q_ARG(qint64, d->realFileSize), Q_ARG(qint64, d->realFileSize)); + QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } bool QFileNetworkReplyPrivate::isFinished() const { - return finished; -} - -void QFileNetworkReplyPrivate::doFinished() -{ - Q_Q(QFileNetworkReply); - finished = true; - emit q->finished(); + return true; } - void QFileNetworkReply::close() { Q_D(QFileNetworkReply); QNetworkReply::close(); d->realFile.close(); - - if (!d->finished) - d->doFinished(); } void QFileNetworkReply::abort() @@ -163,9 +154,6 @@ void QFileNetworkReply::abort() Q_D(QFileNetworkReply); QNetworkReply::close(); d->realFile.close(); - - if (!d->finished) - d->doFinished(); } qint64 QFileNetworkReply::bytesAvailable() const diff --git a/src/network/access/qfilenetworkreply_p.h b/src/network/access/qfilenetworkreply_p.h index 6f10672..125fa2e 100644 --- a/src/network/access/qfilenetworkreply_p.h +++ b/src/network/access/qfilenetworkreply_p.h @@ -66,7 +66,7 @@ class QFileNetworkReply: public QNetworkReply { Q_OBJECT public: - QFileNetworkReply(QObject *parent, const QNetworkRequest &req); + QFileNetworkReply(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); ~QFileNetworkReply(); virtual void abort(); @@ -76,12 +76,9 @@ public: virtual bool isSequential () const; qint64 size() const; - virtual qint64 readData(char *data, qint64 maxlen); Q_DECLARE_PRIVATE(QFileNetworkReply) - Q_PRIVATE_SLOT(d_func(), void _q_startOperation()) - }; class QFileNetworkReplyPrivate: public QNetworkReplyPrivate @@ -92,12 +89,7 @@ public: QFile realFile; qint64 realFileSize; - void _q_startOperation(); - virtual bool isFinished() const; - void doFinished(); - bool finished; - Q_DECLARE_PUBLIC(QFileNetworkReply) }; diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 20baac8..fff7097 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -564,7 +564,8 @@ bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, } -QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket) +QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket, + const QString &extraDetail) { Q_ASSERT(socket); @@ -581,7 +582,7 @@ QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError e errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection closed")); break; case QNetworkReply::TimeoutError: - errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTP request failed")); + errorString = QLatin1String(QT_TRANSLATE_NOOP("QAbstractSocket", "Socket operation timed out")); break; case QNetworkReply::ProxyAuthenticationRequiredError: errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Proxy requires authentication")); @@ -600,7 +601,7 @@ QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError e break; default: // all other errors are treated as QNetworkReply::UnknownNetworkError - errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTP request failed")); + errorString = extraDetail; break; } return errorString; diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 76da883..03cf09c 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -185,7 +185,8 @@ public: void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); - QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket); + QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket, + const QString &extraDetail = QString()); #ifndef QT_NO_COMPRESS bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 39d09aa..b80ae9a 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -260,7 +260,7 @@ bool QHttpNetworkConnectionChannel::sendRequest() // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called // this is needed if the sends an reply before we have finished sending the request. In that // case receiveReply had been called before but ignored the server reply - QMetaObject::invokeMethod(connection, "_q_receiveReply", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); break; } case QHttpNetworkConnectionChannel::ReadingState: @@ -872,7 +872,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket break; } QPointer<QObject> that = connection; - QString errorString = connection->d_func()->errorDetail(errorCode, socket); + QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString()); if (send2Reply) { if (reply) { reply->d_func()->errorString = errorString; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index d27fbe7..e16aedc 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -687,10 +687,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera // 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 + if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) && (req.url().scheme() == QLatin1String("file") || req.url().scheme().isEmpty())) { - return new QFileNetworkReply(this, req); + return new QFileNetworkReply(this, req, op); } QNetworkRequest request = req; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 49a287f..0a8ea5d 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -239,7 +239,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() \note Do not delete the object in the slot connected to this signal. Use deleteLater(). - \sa QNetworkAccessManager::finished() + You can also use isFinished() to check if a QNetworkReply + has finished even before you receive the finished() signal. + + \sa QNetworkAccessManager::finished(), isFinished() */ /*! diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 81bffd9..7088a57 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -994,9 +994,9 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); qint64 ret = 0; - // don't send more than 49152 per call to WSASendTo to avoid getting a WSAENOBUFS + qint64 bytesToSend = len; + for (;;) { - qint64 bytesToSend = qMin<qint64>(49152, len - ret); WSABUF buf; buf.buf = (char*)data + ret; buf.len = bytesToSend; @@ -1007,15 +1007,21 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) ret += qint64(bytesWritten); + int err; if (socketRet != SOCKET_ERROR) { if (ret == len) break; else continue; - } else if (WSAGetLastError() == WSAEWOULDBLOCK) { + } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) { break; + } else if (err == WSAENOBUFS) { + // this function used to not send more than 49152 per call to WSASendTo + // to avoid getting a WSAENOBUFS. However this is a performance regression + // and we think it only appears with old windows versions. We now handle the + // WSAENOBUFS and hope it never appears anyway. + // just go on, the next loop run we will try a smaller number } else { - int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { case WSAECONNRESET: @@ -1029,6 +1035,9 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) } break; } + + // for next send: + bytesToSend = qMin<qint64>(49152, len - ret); } #if defined (QNATIVESOCKETENGINE_DEBUG) diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index dd50c38..9a9b1b5 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -304,6 +304,7 @@ static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) */ QString QSslCertificate::issuerInfo(SubjectInfo info) const { + // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0)); @@ -320,7 +321,11 @@ QString QSslCertificate::issuerInfo(SubjectInfo info) const */ QString QSslCertificate::issuerInfo(const QByteArray &tag) const { - // ### Use a QByteArray for the keys in the map + // lazy init + if (d->issuerInfo.isEmpty() && d->x509) + d->issuerInfo = + _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0)); + return d->issuerInfo.value(QString::fromLatin1(tag)); } @@ -335,6 +340,7 @@ QString QSslCertificate::issuerInfo(const QByteArray &tag) const */ QString QSslCertificate::subjectInfo(SubjectInfo info) const { + // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0)); @@ -350,7 +356,11 @@ QString QSslCertificate::subjectInfo(SubjectInfo info) const */ QString QSslCertificate::subjectInfo(const QByteArray &tag) const { - // ### Use a QByteArray for the keys in the map + // lazy init + if (d->subjectInfo.isEmpty() && d->x509) + d->subjectInfo = + _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0)); + return d->subjectInfo.value(QString::fromLatin1(tag)); } @@ -686,11 +696,11 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509) static bool matchLineFeed(const QByteArray &pem, int *offset) { - char ch = pem.at(*offset); + char ch; // ignore extra whitespace at the end of the line - while (ch == ' ' && *offset < pem.size()) - ch = pem.at(++*offset); + while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ') + ++*offset; if (ch == '\n') { *offset += 1; @@ -722,7 +732,7 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromPem(const QByteAr break; offset = endPos + sizeof(ENDCERTSTRING) - 1; - if (!matchLineFeed(pem, &offset)) + if (offset < pem.size() && !matchLineFeed(pem, &offset)) break; QByteArray decoded = QByteArray::fromBase64( diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index de1583e..892d330 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -553,6 +553,12 @@ void QSslSocketBackendPrivate::transmit() #endif writeBuffer.free(writtenBytes); totalBytesWritten += writtenBytes; + + if (writtenBytes < nextDataBlockSize) { + // break out of the writing loop and try again after we had read + transmitting = true; + break; + } } if (totalBytesWritten > 0) { @@ -586,12 +592,26 @@ void QSslSocketBackendPrivate::transmit() while ((pendingBytes = plainSocket->bytesAvailable()) > 0) { // Read encrypted data from the socket into a buffer. data.resize(pendingBytes); - int decryptedBytesRead = plainSocket->read(data.data(), pendingBytes); + // just peek() here because q_BIO_write could write less data than expected + int encryptedBytesRead = plainSocket->peek(data.data(), pendingBytes); #ifdef QSSLSOCKET_DEBUG - qDebug() << "QSslSocketBackendPrivate::transmit: read" << decryptedBytesRead << "encrypted bytes from the socket"; + qDebug() << "QSslSocketBackendPrivate::transmit: read" << encryptedBytesRead << "encrypted bytes from the socket"; #endif // Write encrypted data from the buffer into the read BIO. - q_BIO_write(readBio, data.constData(), decryptedBytesRead); + int writtenToBio = q_BIO_write(readBio, data.constData(), encryptedBytesRead); + + // do the actual read() here and throw away the results. + if (writtenToBio > 0) { + // ### TODO: make this cheaper by not making it memcpy. E.g. make it work with data=0x0 or make it work with seek + plainSocket->read(data.data(), writtenToBio); + } else { + // ### Better error handling. + q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(SSL_ERRORSTR())); + q->setSocketError(QAbstractSocket::UnknownSocketError); + emit q->error(QAbstractSocket::UnknownSocketError); + return; + } + transmitting = true; } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 556b888..8183f08 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -184,6 +184,9 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); simpleShaderProg->link(); if (!simpleShaderProg->isLinked()) { qCritical() << "Errors linking simple shader:" @@ -324,6 +327,11 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); if (newProg->useOpacityAttribute) newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); + if (newProg->usePmvMatrix) { + newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); + newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); + newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); + } newProg->program->link(); if (!newProg->program->isLinked()) { @@ -424,7 +432,6 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id) "patternColor", "globalOpacity", "depth", - "pmvMatrix", "maskTexture", "fragmentColor", "linearData", @@ -743,6 +750,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() } requiredProgram.useTextureCoords = texCoords; requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); + requiredProgram.usePmvMatrix = true; // At this point, requiredProgram is fully populated so try to find the program in the cache currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index c52e5c0..3ab4ebe 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -253,6 +253,9 @@ struct QGLEngineCachedShaderProg static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; static const GLuint QT_OPACITY_ATTR = 2; +static const GLuint QT_PMV_MATRIX_1_ATTR = 3; +static const GLuint QT_PMV_MATRIX_2_ATTR = 4; +static const GLuint QT_PMV_MATRIX_3_ATTR = 5; class QGLEngineShaderProg; @@ -397,6 +400,7 @@ public: bool useTextureCoords; bool useOpacityAttribute; + bool usePmvMatrix; bool operator==(const QGLEngineShaderProg& other) { // We don't care about the program @@ -431,7 +435,6 @@ public: PatternColor, GlobalOpacity, Depth, - PmvMatrix, MaskTexture, FragmentColor, LinearData, diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index d9a61e9..ee04166 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -63,210 +63,229 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) -static const char* const qglslMainVertexShader = "\ - uniform highp float depth;\ - void setPosition();\ - void main(void)\ - {\ - setPosition();\ - gl_Position.z = depth * gl_Position.w;\ - }"; - -static const char* const qglslMainWithTexCoordsVertexShader = "\ - attribute highp vec2 textureCoordArray; \ - varying highp vec2 textureCoords; \ - uniform highp float depth;\ - void setPosition();\ - void main(void) \ - {\ - setPosition();\ - gl_Position.z = depth * gl_Position.w;\ - textureCoords = textureCoordArray; \ - }"; - -static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ - attribute highp vec2 textureCoordArray; \ - attribute lowp float opacityArray; \ - varying highp vec2 textureCoords; \ - varying lowp float opacity; \ - uniform highp float depth; \ - void setPosition(); \ - void main(void) \ - { \ - setPosition(); \ - gl_Position.z = depth * gl_Position.w; \ - textureCoords = textureCoordArray; \ - opacity = opacityArray; \ - }"; +static const char* const qglslMainVertexShader = "\n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + }\n"; + +static const char* const qglslMainWithTexCoordsVertexShader = "\n\ + attribute highp vec2 textureCoordArray; \n\ + varying highp vec2 textureCoords; \n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + textureCoords = textureCoordArray; \n\ + }\n"; + +static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\n\ + attribute highp vec2 textureCoordArray; \n\ + attribute lowp float opacityArray; \n\ + varying highp vec2 textureCoords; \n\ + varying lowp float opacity; \n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + textureCoords = textureCoordArray; \n\ + opacity = opacityArray; \n\ + }\n"; // NOTE: We let GL do the perspective correction so texture lookups in the fragment // shader are also perspective corrected. -static const char* const qglslPositionOnlyVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ - void setPosition(void)\ - {\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \ - }"; - -static const char* const qglslUntransformedPositionVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - void setPosition(void)\ - {\ - gl_Position = vertexCoordsArray;\ - }"; +static const char* const qglslPositionOnlyVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ + }\n"; + +static const char* const qglslUntransformedPositionVertexShader = "\n\ + attribute highp vec4 vertexCoordsArray; \n\ + void setPosition(void) \n\ + { \n\ + gl_Position = vertexCoordsArray; \n\ + }\n"; // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 -static const char* const qglslPositionWithPatternBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec2 invertedTextureSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 patternTexCoords; \ - void setPosition(void) { \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithPatternBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec2 invertedTextureSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 patternTexCoords; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithPatternBrushVertexShader = qglslPositionWithPatternBrushVertexShader; -static const char* const qglslPatternBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture;\ - uniform lowp vec4 patternColor; \ - varying highp vec2 patternTexCoords;\ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \ +static const char* const qglslPatternBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + uniform lowp vec4 patternColor; \n\ + varying highp vec2 patternTexCoords;\n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\ }\n"; // Linear Gradient Brush -static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec3 linearData; \ - uniform highp mat3 brushTransform; \ - varying mediump float index; \ - void setPosition() { \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec3 linearData; \n\ + uniform highp mat3 brushTransform; \n\ + varying mediump float index; \n\ + void setPosition() \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader = qglslPositionWithLinearGradientBrushVertexShader; -static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture; \ - varying mediump float index; \ - lowp vec4 srcPixel() { \ - mediump vec2 val = vec2(index, 0.5); \ - return texture2D(brushTexture, val); \ +static const char* const qglslLinearGradientBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + varying mediump float index; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + mediump vec2 val = vec2(index, 0.5); \n\ + return texture2D(brushTexture, val); \n\ }\n"; // Conical Gradient Brush -static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ - uniform mediump vec2 halfViewportSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 A; \ - void setPosition(void)\ - {\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - A = hTexCoords.xy * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 A; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + A = hTexCoords.xy * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader = qglslPositionWithConicalGradientBrushVertexShader; static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ #define INVERSE_2PI 0.1591549430918953358 \n\ - uniform lowp sampler2D brushTexture; \n\ - uniform mediump float angle; \ - varying highp vec2 A; \ - lowp vec4 srcPixel() { \ - highp float t; \ - if (abs(A.y) == abs(A.x)) \ - t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \ - else \ - t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \ - return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \ - }"; + uniform lowp sampler2D brushTexture; \n\ + uniform mediump float angle; \n\ + varying highp vec2 A; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + highp float t; \n\ + if (abs(A.y) == abs(A.x)) \n\ + t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ + else \n\ + t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ + return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\ + }\n"; // Radial Gradient Brush -static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ - uniform mediump vec2 halfViewportSize; \ - uniform highp mat3 brushTransform; \ - uniform highp vec2 fmp; \ - varying highp float b; \ - varying highp vec2 A; \ - void setPosition(void) \ - {\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - A = hTexCoords.xy * invertedHTexCoordsZ; \ - b = 2.0 * dot(A, fmp); \ - }"; +static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray;\n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp mat3 brushTransform; \n\ + uniform highp vec2 fmp; \n\ + varying highp float b; \n\ + varying highp vec2 A; \n\ + void setPosition(void) \n\ + {\n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + A = hTexCoords.xy * invertedHTexCoordsZ; \n\ + b = 2.0 * dot(A, fmp); \n\ + }\n"; static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader = qglslPositionWithRadialGradientBrushVertexShader; -static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture; \ - uniform highp float fmp2_m_radius2; \ - uniform highp float inverse_2_fmp2_m_radius2; \ - varying highp float b; \ - varying highp vec2 A; \ - lowp vec4 srcPixel() { \ - highp float c = -dot(A, A); \ - highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \ - return texture2D(brushTexture, val); \ - }"; +static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + uniform highp float fmp2_m_radius2; \n\ + uniform highp float inverse_2_fmp2_m_radius2; \n\ + varying highp float b; \n\ + varying highp vec2 A; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + highp float c = -dot(A, A); \n\ + highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \n\ + return texture2D(brushTexture, val); \n\ + }\n"; // Texture Brush -static const char* const qglslPositionWithTextureBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec2 invertedTextureSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 textureCoords; \ - void setPosition(void) { \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ - }"; +static const char* const qglslPositionWithTextureBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec2 invertedTextureSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 textureCoords; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ + }\n"; static const char* const qglslAffinePositionWithTextureBrushVertexShader = qglslPositionWithTextureBrushVertexShader; @@ -275,148 +294,165 @@ static const char* const qglslAffinePositionWithTextureBrushVertexShader // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, // we emulate GL_REPEAT by only taking the fractional part of the texture coords. // TODO: Special case POT textures which don't need this emulation -static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(brushTexture, fract(textureCoords)); \ - }"; +static const char* const qglslTextureBrushSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() { \n\ + return texture2D(brushTexture, fract(textureCoords)); \n\ + }\n"; #else -static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(brushTexture, textureCoords); \ - }"; +static const char* const qglslTextureBrushSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return texture2D(brushTexture, textureCoords); \n\ + }\n"; #endif -static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp vec4 patternColor; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \ - }"; +static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp vec4 patternColor; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \n\ + }\n"; // Solid Fill Brush -static const char* const qglslSolidBrushSrcFragmentShader = "\ - uniform lowp vec4 fragmentColor; \ - lowp vec4 srcPixel() { \ - return fragmentColor; \ - }"; - -static const char* const qglslImageSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(imageTexture, textureCoords); \ - }"; - -static const char* const qglslCustomSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \ - lowp vec4 srcPixel() { \ - return customShader(imageTexture, textureCoords); \ - }"; - -static const char* const qglslImageSrcWithPatternFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp vec4 patternColor; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \ - }\n"; - -static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - lowp vec4 sample = texture2D(imageTexture, textureCoords); \ - sample.rgb = sample.rgb * sample.a; \ - return sample; \ - }"; - -static const char* const qglslShockingPinkSrcFragmentShader = "\ - lowp vec4 srcPixel() { \ - return vec4(0.98, 0.06, 0.75, 1.0); \ - }"; - -static const char* const qglslMainFragmentShader_ImageArrays = "\ - varying lowp float opacity; \ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel() * opacity; \ - }"; - -static const char* const qglslMainFragmentShader_CMO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \ - }"; - -static const char* const qglslMainFragmentShader_CM = "\ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(compose(srcPixel())); \ - }"; - -static const char* const qglslMainFragmentShader_MO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(srcPixel()*globalOpacity); \ - }"; - -static const char* const qglslMainFragmentShader_M = "\ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(srcPixel()); \ - }"; - -static const char* const qglslMainFragmentShader_CO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = compose(srcPixel()*globalOpacity); \ - }"; - -static const char* const qglslMainFragmentShader_C = "\ - lowp vec4 srcPixel(); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = compose(srcPixel()); \ - }"; - -static const char* const qglslMainFragmentShader_O = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel()*globalOpacity; \ - }"; - -static const char* const qglslMainFragmentShader = "\ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel(); \ - }"; - -static const char* const qglslMaskFragmentShader = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src * mask.a; \ - }"; +static const char* const qglslSolidBrushSrcFragmentShader = "\n\ + uniform lowp vec4 fragmentColor; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return fragmentColor; \n\ + }\n"; + +static const char* const qglslImageSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return texture2D(imageTexture, textureCoords); \n\ + }\n"; + +static const char* const qglslCustomSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return customShader(imageTexture, textureCoords); \n\ + }\n"; + +static const char* const qglslImageSrcWithPatternFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp vec4 patternColor; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\ + }\n"; + +static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\ + sample.rgb = sample.rgb * sample.a; \n\ + return sample; \n\ + }\n"; + +static const char* const qglslShockingPinkSrcFragmentShader = "\n\ + lowp vec4 srcPixel() \n\ + { \n\ + return vec4(0.98, 0.06, 0.75, 1.0); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_ImageArrays = "\n\ + varying lowp float opacity; \n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel() * opacity; \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CMO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CM = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(compose(srcPixel())); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_MO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_M = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(srcPixel()); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = compose(srcPixel()*globalOpacity); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_C = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = compose(srcPixel()); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_O = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel()*globalOpacity; \n\ + }\n"; + +static const char* const qglslMainFragmentShader = "\n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel(); \n\ + }\n"; + +static const char* const qglslMaskFragmentShader = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + {\n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src * mask.a; \n\ + }\n"; // For source over with subpixel antialiasing, the final color is calculated per component as follows // (.a is alpha component, .c is red, green or blue component): @@ -433,23 +469,23 @@ static const char* const qglslMaskFragmentShader = "\ // dest.c = dest.c * (1 - mask.c) + src.c * alpha // -static const char* const qglslRgbMaskFragmentShaderPass1 = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src.a * mask; \ - }"; - -static const char* const qglslRgbMaskFragmentShaderPass2 = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src * mask; \ - }"; +static const char* const qglslRgbMaskFragmentShaderPass1 = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + { \n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src.a * mask; \n\ + }\n"; + +static const char* const qglslRgbMaskFragmentShaderPass2 = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + { \n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src * mask; \n\ + }\n"; /* Left to implement: diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index caa679b..b282676 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -168,12 +168,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader() if (matrixDirty) updateMatrix(); - - if (simpleShaderMatrixUniformDirty) { - const GLuint location = shaderManager->simpleProgram()->uniformLocation("pmvMatrix"); - glUniformMatrix3fv(location, 1, GL_FALSE, (GLfloat*)pmvMatrix); - simpleShaderMatrixUniformDirty = false; - } } void QGL2PaintEngineExPrivate::updateBrushTexture() @@ -392,9 +386,11 @@ void QGL2PaintEngineExPrivate::updateMatrix() matrixDirty = false; - // The actual data has been updated so both shader program's uniforms need updating - simpleShaderMatrixUniformDirty = true; - shaderMatrixUniformDirty = true; + // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only + // need to do this once for every matrix change and persists across all shader programs. + glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]); + glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]); + glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]); dasher.setInvScale(inverseScale); stroker.setInvScale(inverseScale); @@ -932,18 +928,12 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) if (changed) { // The shader program has changed so mark all uniforms as dirty: brushUniformsDirty = true; - shaderMatrixUniformDirty = true; opacityUniformDirty = true; } if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode) updateBrushUniforms(); - if (shaderMatrixUniformDirty) { - glUniformMatrix3fv(location(QGLEngineShaderManager::PmvMatrix), 1, GL_FALSE, (GLfloat*)pmvMatrix); - shaderMatrixUniformDirty = false; - } - if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) { shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); opacityUniformDirty = false; @@ -1955,11 +1945,8 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state == s || old_state->renderHintsChanged) renderHintsChanged(); - if (old_state == s || old_state->matrixChanged) { + if (old_state == s || old_state->matrixChanged) d->matrixDirty = true; - d->simpleShaderMatrixUniformDirty = true; - d->shaderMatrixUniformDirty = true; - } if (old_state == s || old_state->compositionModeChanged) d->compositionModeDirty = true; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index ce1b538..8fa0eff 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -252,8 +252,6 @@ public: bool compositionModeDirty; bool brushTextureDirty; bool brushUniformsDirty; - bool simpleShaderMatrixUniformDirty; - bool shaderMatrixUniformDirty; bool opacityUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 0720170..fed1658 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 393893c..2a8a782 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index a262ded..48e43b2 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -124,9 +124,6 @@ public: }; Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance) -QGLExtensions::Extensions QGLExtensions::glExtensions = 0; -bool QGLExtensions::nvidiaFboNeedsFinish = false; - Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) QGLSignalProxy *QGLSignalProxy::instance() { @@ -154,11 +151,9 @@ public: // falling back to the GL 1 engine.. static bool mac_x1600_check_done = false; if (!mac_x1600_check_done) { - QGLWidget *tmp = 0; - if (!QGLContext::currentContext()) { - tmp = new QGLWidget(); - tmp->makeCurrent(); - } + QGLTemporaryContext *tmp = 0; + if (!QGLContext::currentContext()) + tmp = new QGLTemporaryContext(); if (strstr((char *) glGetString(GL_RENDERER), "X1600")) engineType = QPaintEngine::OpenGL; if (tmp) @@ -178,7 +173,7 @@ public: // from an old GL 1.1 server to a GL 2.x client. In that case we can't // use GL 2.0. if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) - && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader) + && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader) && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) engineType = QPaintEngine::OpenGL2; else @@ -1250,7 +1245,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() static bool cachedDefault = false; static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None; QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); - QGLWidget *dummy = 0; + QGLTemporaryContext *tmpContext = 0; if (currentCtx && currentCtx->d_func()->version_flags_cached) return currentCtx->d_func()->version_flags; @@ -1261,8 +1256,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() } else { if (!hasOpenGL()) return defaultVersionFlags; - dummy = new QGLWidget; - dummy->makeCurrent(); // glGetString() needs a current context + tmpContext = new QGLTemporaryContext; cachedDefault = true; } } @@ -1273,9 +1267,9 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() currentCtx->d_func()->version_flags_cached = true; currentCtx->d_func()->version_flags = versionFlags; } - if (dummy) { + if (tmpContext) { defaultVersionFlags = versionFlags; - delete dummy; + delete tmpContext; } return versionFlags; @@ -1493,6 +1487,8 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) max_texture_size = -1; version_flags_cached = false; version_flags = QGLFormat::OpenGL_Version_None; + extension_flags_cached = false; + extension_flags = 0; current_fbo = 0; default_fbo = 0; active_engine = 0; @@ -2147,7 +2143,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G int tx_h = qt_next_power_of_two(image.height()); QImage img = image; - if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) + if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) { @@ -2169,7 +2165,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G bool genMipmap = false; #endif if (glFormat.directRendering() - && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap) + && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap) && target == GL_TEXTURE_2D && (options & QGLContext::MipmapBindOption)) { @@ -2197,9 +2193,12 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G bool premul = options & QGLContext::PremultipliedAlphaBindOption; GLenum externalFormat; GLuint pixel_type; - if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) { + if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) { externalFormat = GL_BGRA; - pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; + if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) + pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; + else + pixel_type = GL_UNSIGNED_BYTE; } else { externalFormat = GL_RGBA; pixel_type = GL_UNSIGNED_BYTE; @@ -2278,12 +2277,9 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G qgl_byteSwapImage(img, pixel_type); } #ifdef QT_OPENGL_ES - // OpenGL/ES requires that the internal and external formats be identical. - // This is typically used to convert GL_RGBA into GL_BGRA. - // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA. + // OpenGL/ES requires that the internal and external formats be + // identical. internalFormat = externalFormat; - if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV) - pixel_type = GL_UNSIGNED_BYTE; #endif #ifdef QGL_BIND_TEXTURE_DEBUG printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", @@ -4397,6 +4393,13 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str, \note This function temporarily disables depth-testing when the text is drawn. + \note This function can only be used inside a + QPainter::beginNativePainting()/QPainter::endNativePainting() block + if the default OpenGL paint engine is QPaintEngine::OpenGL. To make + QPaintEngine::OpenGL the default GL engine, call + QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the + QApplication constructor. + \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. */ @@ -4868,9 +4871,13 @@ QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, #endif // QT3_SUPPORT -void QGLExtensions::init_extensions() +/* + Returns the GL extensions for the current context. +*/ +QGLExtensions::Extensions QGLExtensions::currentContextExtensions() { QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + Extensions glExtensions; if (extensions.match("GL_ARB_texture_rectangle")) glExtensions |= TextureRectangle; @@ -4931,6 +4938,46 @@ void QGLExtensions::init_extensions() if (extensions.match("GL_EXT_bgra")) glExtensions |= BGRATextureFormat; + + return glExtensions; +} + +/* + Returns the GL extensions for the current QGLContext. If there is no + current QGLContext, a default context will be created and the extensions + for that context will be returned instead. +*/ +QGLExtensions::Extensions QGLExtensions::glExtensions() +{ + QGLTemporaryContext *tmpContext = 0; + static bool cachedDefault = false; + static Extensions defaultExtensions = 0; + QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); + + if (currentCtx && currentCtx->d_func()->extension_flags_cached) + return currentCtx->d_func()->extension_flags; + + if (!currentCtx) { + if (cachedDefault) { + return defaultExtensions; + } else { + tmpContext = new QGLTemporaryContext; + cachedDefault = true; + } + } + + Extensions extensionFlags = currentContextExtensions(); + if (currentCtx) { + currentCtx->d_func()->extension_flags_cached = true; + currentCtx->d_func()->extension_flags = extensionFlags; + } else { + defaultExtensions = extensionFlags; + } + + if (tmpContext) + delete tmpContext; + + return extensionFlags; } /* @@ -4942,7 +4989,6 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi glDevice.setWidget(q); - QGLExtensions::init(); glcx = 0; autoSwap = true; @@ -5191,7 +5237,7 @@ QSize QGLTexture::bindCompressedTexture } #if !defined(QT_OPENGL_ES) if (!glCompressedTexImage2D) { - if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) { + if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) { qWarning("QGLContext::bindTexture(): The GL implementation does " "not support texture compression extensions."); return QSize(); @@ -5230,7 +5276,7 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len) return QSize(); // Bail out if the necessary extension is not present. - if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) { + if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) { qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); return QSize(); } @@ -5340,13 +5386,13 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) // Bail out if the necessary extension is not present. if (textureFormat == GL_ETC1_RGB8_OES) { - if (!(QGLExtensions::glExtensions & + if (!(QGLExtensions::glExtensions() & QGLExtensions::ETC1TextureCompression)) { qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); return QSize(); } } else { - if (!(QGLExtensions::glExtensions & + if (!(QGLExtensions::glExtensions() & QGLExtensions::PVRTCTextureCompression)) { qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); return QSize(); diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 374c6d6..1a04ff9 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -401,6 +401,7 @@ private: friend class QGLContextGroup; friend class QGLSharedResourceGuard; friend class QGLPixmapBlurFilter; + friend class QGLExtensions; friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags(); #ifdef Q_WS_MAC public: diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm index 6ed07e5..c01575b 100644 --- a/src/opengl/qgl_mac.mm +++ b/src/opengl/qgl_mac.mm @@ -116,6 +116,68 @@ extern void qt_mac_dispose_rgn(RgnHandle); //qregion_mac.cpp extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); //qglobal.cpp +/* + QGLTemporaryContext implementation +*/ + +class QGLTemporaryContextPrivate +{ +public: +#ifndef QT_MAC_USE_COCOA + AGLContext ctx; +#else + NSOpenGLContext *ctx; +#endif +}; + +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->ctx = 0; +#ifndef QT_MAC_USE_COCOA + GLint attribs[] = {AGL_RGBA, AGL_NONE}; + AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs); + if (!fmt) { + qDebug("QGLTemporaryContext: Couldn't find any RGB visuals"); + return; + } + d->ctx = aglCreateContext(fmt, 0); + if (!d->ctx) + qDebug("QGLTemporaryContext: Unable to create context"); + else + aglSetCurrentContext(d->ctx); + aglDestroyPixelFormat(fmt); +#else + QMacCocoaAutoReleasePool pool; + NSOpenGLPixelFormatAttribute attribs[] = { 0 }; + NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + if (!fmt) { + qWarning("QGLTemporaryContext: Cannot find any visuals"); + return; + } + + d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0]; + if (!d->ctx) + qWarning("QGLTemporaryContext: Cannot create context"); + else + [d->ctx makeCurrentContext]; + [fmt release]; +#endif +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + if (d->ctx) { +#ifndef QT_MAC_USE_COCOA + aglSetCurrentContext(0); + aglDestroyContext(d->ctx); +#else + [NSOpenGLContext clearCurrentContext]; + [d->ctx release]; +#endif + } +} + bool QGLFormat::hasOpenGL() { return true; @@ -918,54 +980,6 @@ void QGLWidgetPrivate::updatePaintDevice() q->update(); } - -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - -#ifndef QT_MAC_USE_COCOA - GLint attribs[] = { AGL_RGBA, AGL_NONE }; - AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs); - if (!fmt) { - qDebug("QGLExtensions: Couldn't find any RGB visuals"); - return; - } - AGLContext ctx = aglCreateContext(fmt, 0); - if (!ctx) { - qDebug("QGLExtensions: Unable to create context"); - } else { - aglSetCurrentContext(ctx); - init_extensions(); - aglSetCurrentContext(0); - aglDestroyContext(ctx); - } - aglDestroyPixelFormat(fmt); -#else - QMacCocoaAutoReleasePool pool; - NSOpenGLPixelFormatAttribute attribs[] = { 0 }; - NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - if (!fmt) { - qWarning("QGLExtensions: Cannot find any visuals"); - return; - } - - NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0]; - if (!ctx) { - qWarning("QGLExtensions: Cannot create context"); - } else { - [ctx makeCurrentContext]; - init_extensions(); - [NSOpenGLContext clearCurrentContext]; - [ctx release]; - } - [fmt release]; -#endif -} - #endif QT_END_NAMESPACE diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 30f5591..0104f07 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -261,6 +261,60 @@ private: // "ctx" is destroyed. Returns null if nothing is sharing with ctx. Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *); +// GL extension definitions +class QGLExtensions { +public: + enum Extension { + TextureRectangle = 0x00000001, + SampleBuffers = 0x00000002, + GenerateMipmap = 0x00000004, + TextureCompression = 0x00000008, + FragmentProgram = 0x00000010, + MirroredRepeat = 0x00000020, + FramebufferObject = 0x00000040, + StencilTwoSide = 0x00000080, + StencilWrap = 0x00000100, + PackedDepthStencil = 0x00000200, + NVFloatBuffer = 0x00000400, + PixelBufferObject = 0x00000800, + FramebufferBlit = 0x00001000, + NPOTTextures = 0x00002000, + BGRATextureFormat = 0x00004000, + DDSTextureCompression = 0x00008000, + ETC1TextureCompression = 0x00010000, + PVRTCTextureCompression = 0x00020000, + FragmentShader = 0x00040000 + }; + Q_DECLARE_FLAGS(Extensions, Extension) + + static Extensions glExtensions(); + +private: + static Extensions currentContextExtensions(); +}; + +/* + QGLTemporaryContext - the main objective of this class is to have a way of + creating a GL context and making it current, without going via QGLWidget + and friends. At certain points during GL initialization we need a current + context in order decide what GL features are available, and to resolve GL + extensions. Having a light-weight way of creating such a context saves + initial application startup time, and it doesn't wind up creating recursive + conflicts. + The class currently uses a private d pointer to hide the platform specific + types. This could possibly been done inline with #ifdef'ery, but it causes + major headaches on e.g. X11 due to namespace pollution. +*/ +class QGLTemporaryContextPrivate; +class QGLTemporaryContext { +public: + QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0); + ~QGLTemporaryContext(); + +private: + QScopedPointer<QGLTemporaryContextPrivate> d; +}; + class QGLTexture; // This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's @@ -333,10 +387,12 @@ public: uint crWin : 1; uint internal_context : 1; uint version_flags_cached : 1; + uint extension_flags_cached : 1; QPaintDevice *paintDevice; QColor transpColor; QGLContext *q_ptr; QGLFormat::OpenGLVersionFlags version_flags; + QGLExtensions::Extensions extension_flags; QGLContextGroup *group; GLint max_texture_size; @@ -375,41 +431,8 @@ Q_SIGNALS: void aboutToDestroyContext(const QGLContext *context); }; -// GL extension definitions -class QGLExtensions { -public: - enum Extension { - TextureRectangle = 0x00000001, - SampleBuffers = 0x00000002, - GenerateMipmap = 0x00000004, - TextureCompression = 0x00000008, - FragmentProgram = 0x00000010, - MirroredRepeat = 0x00000020, - FramebufferObject = 0x00000040, - StencilTwoSide = 0x00000080, - StencilWrap = 0x00000100, - PackedDepthStencil = 0x00000200, - NVFloatBuffer = 0x00000400, - PixelBufferObject = 0x00000800, - FramebufferBlit = 0x00001000, - NPOTTextures = 0x00002000, - BGRATextureFormat = 0x00004000, - DDSTextureCompression = 0x00008000, - ETC1TextureCompression = 0x00010000, - PVRTCTextureCompression = 0x00020000, - FragmentShader = 0x00040000 - }; - Q_DECLARE_FLAGS(Extensions, Extension) - - static Extensions glExtensions; - static bool nvidiaFboNeedsFinish; - static void init(); // sys dependent - static void init_extensions(); // general: called by init() -}; - Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions) - // Temporarily make a context current if not already current or // shared with the current contex. The previous context is made // current when the object goes out of scope. @@ -533,7 +556,7 @@ bool qt_gl_preferGL2Engine(); inline GLenum qt_gl_preferredTextureFormat() { - return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian + return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian ? GL_BGRA : GL_RGBA; } @@ -542,7 +565,7 @@ inline GLenum qt_gl_preferredTextureTarget() #if defined(QT_OPENGL_ES_2) return GL_TEXTURE_2D; #else - return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) + return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) && !qt_gl_preferGL2Engine() ? GL_TEXTURE_RECTANGLE_NV : GL_TEXTURE_2D; @@ -614,7 +637,7 @@ private: }; -// This class can be used to match GL extensions with doing any mallocs. The +// This class can be used to match GL extensions without doing any mallocs. The // class assumes that the GL extension string ends with a space character, // which it should do on all conformant platforms. Create the object and pass // in a pointer to the extension string, then call match() on each extension diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp index f69ad7b..d4adc8b 100644 --- a/src/opengl/qgl_qws.cpp +++ b/src/opengl/qgl_qws.cpp @@ -83,6 +83,28 @@ static QGLScreen *glScreenForDevice(QPaintDevice *device) return 0; } +/* + QGLTemporaryContext implementation +*/ + +class QGLTemporaryContextPrivate +{ +public: + QGLWidget *widget; +}; + +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->widget = new QGLWidget; + d->widget->makeCurrent(); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + delete d->widget; +} + /***************************************************************************** QOpenGL debug facilities *****************************************************************************/ @@ -311,36 +333,4 @@ void QGLWidget::setColormap(const QGLColormap &) { } -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - - // We need a context current to initialize the extensions, - // but getting a valid EGLNativeWindowType this early can be - // problematic under QWS. So use a pbuffer instead. - // - // Unfortunately OpenGL/ES 2.0 systems don't normally - // support pbuffers, so we have no choice but to try - // our luck with a window on those systems. -#if defined(QT_OPENGL_ES_2) - QGLWidget tmpWidget; - tmpWidget.makeCurrent(); - - init_extensions(); - - tmpWidget.doneCurrent(); -#else - QGLPixelBuffer pbuffer(16, 16); - pbuffer.makeCurrent(); - - init_extensions(); - - pbuffer.doneCurrent(); -#endif -} - QT_END_NAMESPACE diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 443fbf2..ed4814f 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -551,7 +551,7 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi) QVarLengthArray<int> iAttributes(40); QVarLengthArray<int> iValues(40); int i = 0; - bool has_sample_buffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers; + bool has_sample_buffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers; iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0 iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1 @@ -628,52 +628,14 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi) /* - Creates a temporary GL context and makes it current - - cleans up when the object is destructed. + QGLTemporaryContext implementation */ Q_GUI_EXPORT const QString qt_getRegisteredWndClass(); -class QGLTempContext +class QGLTemporaryContextPrivate { public: - QGLTempContext(bool directRendering, QWidget *parent = 0) - { - QString windowClassName = qt_getRegisteredWndClass(); - if (parent && !parent->internalWinId()) - parent = parent->nativeParentWidget(); - - dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(), - 0, 0, 0, 0, 1, 1, - parent ? parent->winId() : 0, 0, qWinAppInst(), 0); - - dmy_pdc = GetDC(dmy_id); - PIXELFORMATDESCRIPTOR dmy_pfd; - memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - dmy_pfd.nVersion = 1; - dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; - dmy_pfd.iPixelType = PFD_TYPE_RGBA; - if (!directRendering) - dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT; - - int dmy_pf = ChoosePixelFormat(dmy_pdc, &dmy_pfd); - SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd); - dmy_rc = wglCreateContext(dmy_pdc); - old_dc = wglGetCurrentDC(); - old_context = wglGetCurrentContext(); - wglMakeCurrent(dmy_pdc, dmy_rc); - } - - ~QGLTempContext() { - wglMakeCurrent(dmy_pdc, 0); - wglDeleteContext(dmy_rc); - ReleaseDC(dmy_id, dmy_pdc); - DestroyWindow(dmy_id); - if (old_dc && old_context) - wglMakeCurrent(old_dc, old_context); - } - HDC dmy_pdc; HGLRC dmy_rc; HDC old_dc; @@ -681,6 +643,45 @@ public: WId dmy_id; }; +QGLTemporaryContext::QGLTemporaryContext(bool directRendering, QWidget *parent) + : d(new QGLTemporaryContextPrivate) +{ + QString windowClassName = qt_getRegisteredWndClass(); + if (parent && !parent->internalWinId()) + parent = parent->nativeParentWidget(); + + d->dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(), + 0, 0, 0, 0, 1, 1, + parent ? parent->winId() : 0, 0, qWinAppInst(), 0); + + d->dmy_pdc = GetDC(d->dmy_id); + PIXELFORMATDESCRIPTOR dmy_pfd; + memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + dmy_pfd.nVersion = 1; + dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + dmy_pfd.iPixelType = PFD_TYPE_RGBA; + if (!directRendering) + dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT; + + int dmy_pf = ChoosePixelFormat(d->dmy_pdc, &dmy_pfd); + SetPixelFormat(d->dmy_pdc, dmy_pf, &dmy_pfd); + d->dmy_rc = wglCreateContext(d->dmy_pdc); + d->old_dc = wglGetCurrentDC(); + d->old_context = wglGetCurrentContext(); + wglMakeCurrent(d->dmy_pdc, d->dmy_rc); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + wglMakeCurrent(d->dmy_pdc, 0); + wglDeleteContext(d->dmy_rc); + ReleaseDC(d->dmy_id, d->dmy_pdc); + DestroyWindow(d->dmy_id); + if (d->old_dc && d->old_context) + wglMakeCurrent(d->old_dc, d->old_context); +} + bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); @@ -721,10 +722,10 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) myDc = GetDC(d->win); } - // NB! the QGLTempContext object is needed for the + // NB! the QGLTemporaryContext object is needed for the // wglGetProcAddress() calls to succeed and are absolutely // necessary - don't remove! - QGLTempContext tmp_ctx(d->glFormat.directRendering(), widget); + QGLTemporaryContext tmp_ctx(d->glFormat.directRendering(), widget); if (!myDc) { qWarning("QGLContext::chooseContext(): Paint device cannot be null"); @@ -965,7 +966,7 @@ int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc) iAttributes[i++] = 1; } int si = 0; - bool trySampleBuffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers; + bool trySampleBuffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers; if (trySampleBuffers && d->glFormat.sampleBuffers()) { iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = TRUE; @@ -1471,15 +1472,4 @@ void QGLWidget::setColormap(const QGLColormap & c) } } -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - QGLTempContext temp_ctx(QGLFormat::defaultFormat().directRendering()); - init_extensions(); -} - QT_END_NAMESPACE diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp index 460f10d..00a125a 100644 --- a/src/opengl/qgl_wince.cpp +++ b/src/opengl/qgl_wince.cpp @@ -95,8 +95,27 @@ public: #include <qcolor.h> +/* + QGLTemporaryContext implementation +*/ +class QGLTemporaryContextPrivate +{ +public: + QGLWidget *widget; +}; +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->widget = new QGLWidget; + d->widget->makeCurrent(); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + delete d->widget; +} /***************************************************************************** QGLFormat Win32/WGL-specific code @@ -627,21 +646,4 @@ void QGLWidget::setColormap(const QGLColormap & c) } } -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - - // We need a context current to initialize the extensions. - QGLWidget tmpWidget; - tmpWidget.makeCurrent(); - - init_extensions(); - - tmpWidget.doneCurrent(); -} - QT_END_NAMESPACE diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index e883ddc..61a16be 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -549,7 +549,7 @@ void *QGLContext::chooseVisual() bool triedDouble = false; bool triedSample = false; if (fmt.sampleBuffers()) - fmt.setSampleBuffers(QGLExtensions::glExtensions & QGLExtensions::SampleBuffers); + fmt.setSampleBuffers(QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers); while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) { if (!fmt.rgba() && bufDepths[i] > 1) { i++; @@ -1132,71 +1132,70 @@ void *QGLContext::getProcAddress(const QString &proc) const return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data())); } -// -// This class is used to create a temporary, minimal GL context, which is used -// to retrive GL version and extension info. It's significantly faster to -// construct than a QGLWidget, and it doesn't have the recursive creation -// problem that QGLWidget would have. E.g. creating a temporary QGLWidget to -// retrieve GL info as part of the QGLWidget initialization. -// -class QGLTempContext -{ +/* + QGLTemporaryContext implementation +*/ + +class QGLTemporaryContextPrivate { public: - QGLTempContext(int screen = 0) : - initialized(false), - old_drawable(0), - old_context(0) - { - int attribs[] = {GLX_RGBA, XNone}; - XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs); - if (!vi) { - qWarning("QGLTempContext: No GL capable X visuals available."); - return; - } + bool initialized; + Window drawable; + GLXContext context; + GLXDrawable oldDrawable; + GLXContext oldContext; +}; - int useGL; - glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL); - if (!useGL) { - XFree(vi); - return; - } +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->initialized = false; + d->oldDrawable = 0; + d->oldContext = 0; + int screen = 0; + + int attribs[] = {GLX_RGBA, XNone}; + XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs); + if (!vi) { + qWarning("QGLTempContext: No GL capable X visuals available."); + return; + } - old_drawable = glXGetCurrentDrawable(); - old_context = glXGetCurrentContext(); - - XSetWindowAttributes a; - a.colormap = qt_gl_choose_cmap(X11->display, vi); - drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen), - 0, 0, 1, 1, 0, - vi->depth, InputOutput, vi->visual, - CWColormap, &a); - context = glXCreateContext(X11->display, vi, 0, True); - if (context && glXMakeCurrent(X11->display, drawable, context)) { - initialized = true; - } else { - qWarning("QGLTempContext: Unable to create GL context."); - XDestroyWindow(X11->display, drawable); - } + int useGL; + glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL); + if (!useGL) { XFree(vi); + return; } - ~QGLTempContext() { - if (initialized) { - glXMakeCurrent(X11->display, 0, 0); - glXDestroyContext(X11->display, context); - XDestroyWindow(X11->display, drawable); - } - if (old_drawable && old_context) - glXMakeCurrent(X11->display, old_drawable, old_context); + d->oldDrawable = glXGetCurrentDrawable(); + d->oldContext = glXGetCurrentContext(); + + XSetWindowAttributes a; + a.colormap = qt_gl_choose_cmap(X11->display, vi); + d->drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen), + 0, 0, 1, 1, 0, + vi->depth, InputOutput, vi->visual, + CWColormap, &a); + d->context = glXCreateContext(X11->display, vi, 0, True); + if (d->context && glXMakeCurrent(X11->display, d->drawable, d->context)) { + d->initialized = true; + } else { + qWarning("QGLTempContext: Unable to create GL context."); + XDestroyWindow(X11->display, d->drawable); } + XFree(vi); +} -private: - bool initialized; - Window drawable; - GLXContext context; - GLXDrawable old_drawable; - GLXContext old_context; -}; +QGLTemporaryContext::~QGLTemporaryContext() +{ + if (d->initialized) { + glXMakeCurrent(X11->display, 0, 0); + glXDestroyContext(X11->display, d->context); + XDestroyWindow(X11->display, d->drawable); + } + if (d->oldDrawable && d->oldContext) + glXMakeCurrent(X11->display, d->oldDrawable, d->oldContext); +} /***************************************************************************** QGLOverlayWidget (Internal overlay class for X11) @@ -1632,27 +1631,6 @@ void QGLWidget::setColormap(const QGLColormap & c) delete [] cmw; } -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - - QGLTempContext context; - init_extensions(); - - // nvidia 9x.xx unix drivers contain a bug which requires us to call glFinish before releasing an fbo - // to avoid painting artifacts - const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION))); - const int pos = versionString.indexOf("NVIDIA"); - if (pos >= 0) { - const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat(); - nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0; - } -} - // Solaris defines glXBindTexImageEXT as part of the GL library #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*); @@ -1668,13 +1646,17 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice) resolvedTextureFromPixmap = true; // Check to see if we have NPOT texture support - if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) && + if ( !(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)) { return false; // Can't use TFP without NPOT } + const QX11Info *xinfo = qt_x11Info(paintDevice); - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + Display *display = xinfo ? xinfo->display() : X11->display; + int screen = xinfo ? xinfo->screen() : X11->defaultScreen; + + QGLExtensionMatcher extensions(glXQueryExtensionsString(display, screen)); if (extensions.match("GLX_EXT_texture_from_pixmap")) { glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT"); glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT"); diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 85daf95..572834b 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -55,112 +55,115 @@ QT_BEGIN_NAMESPACE bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual); -// -// QGLTempContext is a class for creating a temporary GL context -// (which is needed during QGLWidget initialization to retrieve GL -// extension info). Faster to construct than a full QGLWidget. -// -class QGLTempContext + +/* + QGLTemporaryContext implementation +*/ + +class QGLTemporaryContextPrivate { public: - QGLTempContext(int screen = 0) : - initialized(false), - window(0), - context(0), - surface(0) - { - display = eglGetDisplay(EGLNativeDisplayType(X11->display)); + bool initialized; + Window window; + EGLContext context; + EGLSurface surface; + EGLDisplay display; +}; - if (!eglInitialize(display, NULL, NULL)) { - qWarning("QGLTempContext: Unable to initialize EGL display."); - return; - } +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->initialized = false; + d->window = 0; + d->context = 0; + d->surface = 0; + int screen = 0; + + d->display = eglGetDisplay(EGLNativeDisplayType(X11->display)); - EGLConfig config; - int numConfigs = 0; - EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + if (!eglInitialize(d->display, NULL, NULL)) { + qWarning("QGLTemporaryContext: Unable to initialize EGL display."); + return; + } + + EGLConfig config; + int numConfigs = 0; + EGLint attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, #ifdef QT_OPENGL_ES_2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #endif - EGL_NONE - }; + EGL_NONE + }; - eglChooseConfig(display, attribs, &config, 1, &numConfigs); - if (!numConfigs) { - qWarning("QGLTempContext: No EGL configurations available."); - return; - } + eglChooseConfig(d->display, attribs, &config, 1, &numConfigs); + if (!numConfigs) { + qWarning("QGLTemporaryContext: No EGL configurations available."); + return; + } - XVisualInfo visualInfo; - XVisualInfo *vi; - int numVisuals; - EGLint id = 0; - - eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &id); - if (id == 0) { - // EGL_NATIVE_VISUAL_ID is optional and might not be supported - // on some implementations - we'll have to do it the hard way - QX11Info xinfo; - qt_egl_setup_x11_visual(visualInfo, display, config, xinfo, false); - } else { - visualInfo.visualid = id; - } - vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); - if (!vi || numVisuals < 1) { - qWarning("QGLTempContext: Unable to get X11 visual info id."); - return; - } + XVisualInfo visualInfo; + XVisualInfo *vi; + int numVisuals; + EGLint id = 0; + + eglGetConfigAttrib(d->display, config, EGL_NATIVE_VISUAL_ID, &id); + if (id == 0) { + // EGL_NATIVE_VISUAL_ID is optional and might not be supported + // on some implementations - we'll have to do it the hard way + QX11Info xinfo; + qt_egl_setup_x11_visual(visualInfo, d->display, config, xinfo, false); + } else { + visualInfo.visualid = id; + } + vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); + if (!vi || numVisuals < 1) { + qWarning("QGLTemporaryContext: Unable to get X11 visual info id."); + return; + } - window = XCreateWindow(X11->display, RootWindow(X11->display, screen), - 0, 0, 1, 1, 0, - vi->depth, InputOutput, vi->visual, - 0, 0); + d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen), + 0, 0, 1, 1, 0, + vi->depth, InputOutput, vi->visual, + 0, 0); - surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType) window, NULL); + d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL); - if (surface == EGL_NO_SURFACE) { - qWarning("QGLTempContext: Error creating EGL surface."); - XFree(vi); - XDestroyWindow(X11->display, window); - return; - } + if (d->surface == EGL_NO_SURFACE) { + qWarning("QGLTemporaryContext: Error creating EGL surface."); + XFree(vi); + XDestroyWindow(X11->display, d->window); + return; + } - EGLint contextAttribs[] = { + EGLint contextAttribs[] = { #ifdef QT_OPENGL_ES_2 - EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_CONTEXT_CLIENT_VERSION, 2, #endif - EGL_NONE - }; - context = eglCreateContext(display, config, 0, contextAttribs); - if (context != EGL_NO_CONTEXT - && eglMakeCurrent(display, surface, surface, context)) - { - initialized = true; - } else { - qWarning("QGLTempContext: Error creating EGL context."); - eglDestroySurface(display, surface); - XDestroyWindow(X11->display, window); - } - XFree(vi); + EGL_NONE + }; + d->context = eglCreateContext(d->display, config, 0, contextAttribs); + if (d->context != EGL_NO_CONTEXT + && eglMakeCurrent(d->display, d->surface, d->surface, d->context)) + { + d->initialized = true; + } else { + qWarning("QGLTemporaryContext: Error creating EGL context."); + eglDestroySurface(d->display, d->surface); + XDestroyWindow(X11->display, d->window); } + XFree(vi); +} - ~QGLTempContext() { - if (initialized) { - eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(display, context); - eglDestroySurface(display, surface); - XDestroyWindow(X11->display, window); - } +QGLTemporaryContext::~QGLTemporaryContext() +{ + if (d->initialized) { + eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(d->display, d->context); + eglDestroySurface(d->display, d->surface); + XDestroyWindow(X11->display, d->window); } - -private: - bool initialized; - Window window; - EGLContext context; - EGLSurface surface; - EGLDisplay display; -}; +} bool QGLFormat::hasOpenGLOverlays() { @@ -547,19 +550,6 @@ void QGLWidget::setColormap(const QGLColormap &) { } -void QGLExtensions::init() -{ - static bool init_done = false; - - if (init_done) - return; - init_done = true; - - // We need a context current to initialize the extensions. - QGLTempContext context; - init_extensions(); -} - // Re-creates the EGL surface if the window ID has changed or if force is true void QGLWidgetPrivate::recreateEglSurface(bool force) { diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index ed21923..ce80796 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -396,7 +396,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); fbo_guard.setContext(ctx); - bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); + bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx))) return; @@ -466,7 +466,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, } if (attachment == QGLFramebufferObject::CombinedDepthStencil - && (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) { + && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension glGenRenderbuffers(1, &depth_stencil_buffer); Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); @@ -1028,8 +1028,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const */ bool QGLFramebufferObject::hasOpenGLFramebufferObjects() { - QGLExtensions::init(); - return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); + return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); } /*! @@ -1188,8 +1187,7 @@ bool QGLFramebufferObject::isBound() const */ bool QGLFramebufferObject::hasOpenGLFramebufferBlit() { - QGLExtensions::init(); - return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit); + return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit); } /*! @@ -1229,7 +1227,7 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q GLbitfield buffers, GLenum filter) { - if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) + if (!(QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) return; const QGLContext *ctx = QGLContext::currentContext(); diff --git a/src/opengl/qglpixelbuffer_mac.mm b/src/opengl/qglpixelbuffer_mac.mm index 49c1845..6731dd8 100644 --- a/src/opengl/qglpixelbuffer_mac.mm +++ b/src/opengl/qglpixelbuffer_mac.mm @@ -92,7 +92,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge GLenum target = GL_TEXTURE_2D; - if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) + if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) && (size.width() != nearest_gl_texture_size(size.width()) || size.height() != nearest_gl_texture_size(size.height()))) { @@ -223,7 +223,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge GLenum target = GL_TEXTURE_2D; - if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) + if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) && (size.width() != nearest_gl_texture_size(size.width()) || size.height() != nearest_gl_texture_size(size.height()))) { diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h index f40b7c5..c85dc5a 100644 --- a/src/opengl/qglpixelbuffer_p.h +++ b/src/opengl/qglpixelbuffer_p.h @@ -154,7 +154,6 @@ class QGLPixelBufferPrivate { public: QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), pbuf(0), ctx(0) { - QGLExtensions::init(); #ifdef Q_WS_WIN dc = 0; #elif defined(Q_WS_MACX) diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp index a986ccf..8d0d105 100644 --- a/src/opengl/qglpixelbuffer_win.cpp +++ b/src/opengl/qglpixelbuffer_win.cpp @@ -221,7 +221,7 @@ static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f } if ((f.redBufferSize() > 8 || f.greenBufferSize() > 8 || f.blueBufferSize() > 8 || f.alphaBufferSize() > 8) - && (QGLExtensions::glExtensions & QGLExtensions::NVFloatBuffer)) + && (QGLExtensions::glExtensions() & QGLExtensions::NVFloatBuffer)) { attribs[i++] = WGL_FLOAT_COMPONENTS_NV; attribs[i++] = TRUE; @@ -368,11 +368,9 @@ void QGLPixelBuffer::releaseFromDynamicTexture() bool QGLPixelBuffer::hasOpenGLPbuffers() { bool ret = false; - QGLWidget *dmy = 0; - if (!QGLContext::currentContext()) { - dmy = new QGLWidget; - dmy->makeCurrent(); - } + QGLTemporaryContext *tmpContext = 0; + if (!QGLContext::currentContext()) + tmpContext = new QGLTemporaryContext; PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtensionsStringARB) { @@ -382,8 +380,8 @@ bool QGLPixelBuffer::hasOpenGLPbuffers() ret = true; } } - if (dmy) - delete dmy; + if (tmpContext) + delete tmpContext; return ret; } diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index c823187..57918d0 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -108,6 +108,10 @@ static bool DEBUG_TEMP_FLAG; #define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str); #endif +#ifdef Q_WS_X11 +static bool qt_nvidiaFboNeedsFinish = false; +#endif + static inline void qt_glColor4ubv(unsigned char *col) { glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f); @@ -423,7 +427,7 @@ inline void QGLOffscreen::release() #ifdef Q_WS_X11 // workaround for bug in nvidia driver versions 9x.xx - if (QGLExtensions::nvidiaFboNeedsFinish) + if (qt_nvidiaFboNeedsFinish) glFinish(); #endif @@ -477,7 +481,7 @@ inline QGLContext *QGLOffscreen::context() const bool QGLOffscreen::isSupported() { - return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); // for fbo + return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); // for fbo } struct QDrawQueueItem @@ -1266,7 +1270,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) for (int j = 0; j < 4; ++j) d->mv_matrix[i][j] = (i == j ? qreal(1) : qreal(0)); - bool has_frag_program = (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram) + bool has_frag_program = (QGLExtensions::glExtensions() & QGLExtensions::FragmentProgram) && (pdev->devType() != QInternal::Pixmap); QGLContext *ctx = const_cast<QGLContext *>(d->device->context()); @@ -1279,11 +1283,27 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) has_frag_program = qt_resolve_frag_program_extensions(ctx) && qt_resolve_version_1_3_functions(ctx); d->use_stencil_method = d->device->format().stencil() - && (QGLExtensions::glExtensions & QGLExtensions::StencilWrap); + && (QGLExtensions::glExtensions() & QGLExtensions::StencilWrap); if (d->device->format().directRendering() - && (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide)) + && (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide)) d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx); +#ifdef Q_WS_X11 + static bool nvidia_workaround_needs_init = true; + if (nvidia_workaround_needs_init) { + // nvidia 9x.xx unix drivers contain a bug which requires us to + // call glFinish before releasing an fbo to avoid painting + // artifacts + const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION))); + const int pos = versionString.indexOf("NVIDIA"); + if (pos >= 0) { + const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat(); + qt_nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0; + } + nvidia_workaround_needs_init = false; + } +#endif + #ifndef QT_OPENGL_ES if (!ctx->d_ptr->internal_context) { glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]); @@ -1333,10 +1353,10 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers) + if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) glDisable(GL_MULTISAMPLE); glDisable(GL_TEXTURE_2D); - if (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) + if (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) glDisable(GL_TEXTURE_RECTANGLE_NV); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); @@ -1534,7 +1554,7 @@ void QOpenGLPaintEnginePrivate::updateGradient(const QBrush &brush, const QRectF #ifdef QT_OPENGL_ES Q_UNUSED(brush); #else - bool has_mirrored_repeat = QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat; + bool has_mirrored_repeat = QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat; Qt::BrushStyle style = brush.style(); QTransform m = brush.transform(); @@ -2098,7 +2118,7 @@ static inline bool needsEmulation(Qt::BrushStyle style) { return !(style == Qt::SolidPattern || (style == Qt::LinearGradientPattern - && (QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat))); + && (QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat))); } void QOpenGLPaintEnginePrivate::updateUseEmulation() @@ -2420,12 +2440,12 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints) d->high_quality_antialiasing = true; } else { d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers) + if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) glEnable(GL_MULTISAMPLE); } } else { d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers) + if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) glDisable(GL_MULTISAMPLE); } @@ -2435,14 +2455,14 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints) if (!d->offscreen.isValid()) { DEBUG_ONCE_STR("Unable to initialize offscreen, disabling high quality antialiasing"); d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers) + if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) glEnable(GL_MULTISAMPLE); } } d->has_antialiasing = d->high_quality_antialiasing || ((hints & QPainter::Antialiasing) - && (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)); + && (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)); } diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 1bfb6e3..aa80664 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -341,7 +341,7 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull()) { if (external_format == GL_RGB) { - const QImage tx = m_source.convertToFormat(QImage::Format_RGB888); + const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true); glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index a5e0239..55aa1d0 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -39,10 +39,19 @@ ** ****************************************************************************/ +#include <QDebug> + #include <private/qgl_p.h> #include <private/qegl_p.h> #include <private/qeglproperties_p.h> + +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) #include <private/qpaintengineex_opengl2_p.h> +#endif + +#ifndef QT_OPENGL_ES_2 +#include <private/qpaintengine_opengl_p.h> +#endif #include "qpixmapdata_x11gl_p.h" @@ -187,7 +196,14 @@ QX11GLPixmapData::~QX11GLPixmapData() { } -static QGL2PaintEngineEx* qt_gl2_engine_for_pixmaps = 0; +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) +Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine) +#endif + +#ifndef QT_OPENGL_ES_2 +Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_pixmap_engine) +#endif + QPaintEngine* QX11GLPixmapData::paintEngine() const { @@ -202,18 +218,41 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const : qPixmapRGBSharedEglContext); } - if (!qt_gl2_engine_for_pixmaps) - qt_gl2_engine_for_pixmaps = new QGL2PaintEngineEx(); + QPaintEngine* engine; + +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) + engine = qt_gl_pixmap_engine(); +#elif defined(QT_OPENGL_ES_2) + engine = qt_gl_pixmap_2_engine(); +#else + if (qt_gl_preferGL2Engine()) + engine = qt_gl_pixmap_2_engine(); + else + engine = qt_gl_pixmap_engine(); +#endif + + // Support multiple painters on multiple pixmaps simultaniously - if (qt_gl2_engine_for_pixmaps->isActive()) { + if (engine->isActive()) { qWarning("Pixmap paint engine already active"); - QPaintEngine* engine = new QGL2PaintEngineEx(); + +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) + engine = new QOpenGLPaintEngine; +#elif defined(QT_OPENGL_ES_2) + engine = new QGL2PaintEngineEx; +#else + if (qt_gl_preferGL2Engine()) + engine = new QGL2PaintEngineEx; + else + engine = new QOpenGLPaintEngine; +#endif + engine->setAutoDestruct(true); return engine; } - return qt_gl2_engine_for_pixmaps; + return engine; } void QX11GLPixmapData::beginPaint() diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 8ee4361..7a565e6 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -295,7 +295,6 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window) : QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate) { Q_ASSERT(window->isTopLevel()); - QGLExtensions::init(); d_ptr->pb = 0; d_ptr->fbo = 0; d_ptr->ctx = 0; @@ -520,7 +519,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & glDisable(GL_SCISSOR_TEST); - if (d_ptr->fbo && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) { + if (d_ptr->fbo && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) { const int h = d_ptr->fbo->height(); const int sx0 = br.left(); @@ -698,7 +697,7 @@ void QGLWindowSurface::updateGeometry() { } if (d_ptr->destructive_swap_buffers - && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject) + && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject) && (d_ptr->fbo || !d_ptr->tried_fbo) && qt_gl_preferGL2Engine()) { @@ -712,7 +711,7 @@ void QGLWindowSurface::updateGeometry() { format.setInternalTextureFormat(GLenum(GL_RGBA)); format.setTextureTarget(target); - if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) + if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) format.setSamples(8); d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 1cbfdaf..f27440e 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -552,6 +552,34 @@ QImage *QDirectFBPixmapData::buffer() return &lockedImage; } + +bool QDirectFBPixmapData::scroll(int dx, int dy, const QRect &rect) +{ + if (!dfbSurface) { + return false; + } + unlockSurface(); + DFBResult result = dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + result = dfbSurface->SetPorterDuff(dfbSurface, DSPD_NONE); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + + const DFBRectangle source = { rect.x(), rect.y(), rect.width(), rect.height() }; + result = dfbSurface->Blit(dfbSurface, dfbSurface, &source, source.x + dx, source.y + dy); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + + return true; +} + void QDirectFBPixmapData::invalidate() { if (dfbSurface) { @@ -568,6 +596,3 @@ void QDirectFBPixmapData::invalidate() QT_END_NAMESPACE #endif // QT_NO_QWS_DIRECTFB - - - diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index f9b14a9..da6edc6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -81,6 +81,7 @@ public: virtual QImage toImage() const; virtual QPaintEngine *paintEngine() const; virtual QImage *buffer(); + virtual bool scroll(int dx, int dy, const QRect &rect); // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice virtual int metric(QPaintDevice::PaintDeviceMetric m) const { return QDirectFBPaintDevice::metric(m); } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index cb9c921..6764e75 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -378,9 +378,6 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, return; } screen->flipSurface(dfbSurface, flipFlags, region, offset); - if (noSystemBackground) { - dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); - } #else setOpaque(windowOpacity != 0xff); if (mode == Offscreen) { diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index b66f8f9..3af8b40 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -1,6 +1,6 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.6.1 + VERSION=4.6.2 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qbase.pri b/src/qbase.pri index d1a2a75..710a2b6 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.6.1 + VERSION=4.6.2 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } @@ -94,31 +94,17 @@ symbian { DEFINES+=QT_MAKEDLL TARGET.CAPABILITY = All -Tcb - defBlock = \ - "$${LITERAL_HASH}ifdef WINSCW" \ - "DEFFILE ../s60installs/bwins/$${TARGET}.def" \ - "$${LITERAL_HASH}elif defined EABI" \ - "DEFFILE ../s60installs/eabi/$${TARGET}.def" \ - "$${LITERAL_HASH}endif" - - contains(QT_CONFIG, private_tests) { - #When building autotest configuration, there are extra exports from - #the Qt DLLs, which we don't want in the frozen DEF files. - MMP_RULES += EXPORTUNFROZEN - } else { - #When building without autotests, DEF files are used by default. - #This is to maintain binary compatibility with previous releases. - - #with defBlock enabled, removed exported symbols are treated as errors - #and there is binary compatibility between successive builds. - #with defBlock disabled, binary compatibility is broken every time you build - MMP_RULES += defBlock - - #with EXPORTUNFROZEN enabled, new exports are included in the dll without - #needing to run abld freeze, however binary compatibility is only maintained - #for symbols that are frozen (and only if defBlock is also enabled) - #the downside of EXPORTUNFROZEN is that the linker gets run twice - #MMP_RULES += EXPORTUNFROZEN + # When building without autotests, DEF files are used by default. + # This is to maintain binary compatibility with previous releases. + # To explicitly disable DEF files usage, eg. when lots of code churn is + # going on, and functions may be added and removed before shipping, + # configure with -no-usedeffiles + # WARNING - disabling DEF files *will* break BC with previous released versions + # of Qt, and the only compatibility will be between this build of Qt and anything + # built in this exact environment. *Never* use this when building a version + # for release. + contains(CONFIG, def_files) { + defFilePath=../s60installs } } load(armcc_warnings) diff --git a/src/s60installs/backup_registration.xml b/src/s60installs/backup_registration.xml new file mode 100644 index 0000000..e026140 --- /dev/null +++ b/src/s60installs/backup_registration.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" standalone="yes"?> +<backup_registration> + <system_backup/> + <restore requires_reboot = "no"/> +</backup_registration> diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index fe752c8..e7e890c 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4398,4 +4398,5 @@ EXPORTS ?object@WrappedEvent@QStateMachine@@QBEPAVQObject@@XZ @ 4397 NONAME ; class QObject * QStateMachine::WrappedEvent::object(void) const ?sender@SignalEvent@QStateMachine@@QBEPAVQObject@@XZ @ 4398 NONAME ; class QObject * QStateMachine::SignalEvent::sender(void) const ?signalIndex@SignalEvent@QStateMachine@@QBEHXZ @ 4399 NONAME ; int QStateMachine::SignalEvent::signalIndex(void) const + ?disconnectOne@QMetaObject@@SA_NPBVQObject@@H0H@Z @ 4400 NONAME ; bool QMetaObject::disconnectOne(class QObject const *, int, class QObject const *, int) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 7a629d7..da65230 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -10694,10 +10694,10 @@ EXPORTS ?swipeAngle@QSwipeGesture@@QBEMXZ @ 10693 NONAME ; float QSwipeGesture::swipeAngle(void) const ?symbianEventFilter@QApplication@@UAE_NPBVQSymbianEvent@@@Z @ 10694 NONAME ; bool QApplication::symbianEventFilter(class QSymbianEvent const *) ?symbianFilterEvent@QInputContext@@UAE_NPAVQWidget@@PBVQSymbianEvent@@@Z @ 10695 NONAME ; bool QInputContext::symbianFilterEvent(class QWidget *, class QSymbianEvent const *) - ?symbianHandleCommand@QApplicationPrivate@@QAEHH@Z @ 10696 NONAME ; int QApplicationPrivate::symbianHandleCommand(int) + ?symbianHandleCommand@QApplicationPrivate@@QAEHH@Z @ 10696 NONAME ABSENT ; int QApplicationPrivate::symbianHandleCommand(int) ?symbianProcessEvent@QApplication@@QAEHPBVQSymbianEvent@@@Z @ 10697 NONAME ; int QApplication::symbianProcessEvent(class QSymbianEvent const *) - ?symbianProcessWsEvent@QApplicationPrivate@@QAEHPBVTWsEvent@@@Z @ 10698 NONAME ; int QApplicationPrivate::symbianProcessWsEvent(class TWsEvent const *) - ?symbianResourceChange@QApplicationPrivate@@QAEHH@Z @ 10699 NONAME ; int QApplicationPrivate::symbianResourceChange(int) + ?symbianProcessWsEvent@QApplicationPrivate@@QAEHPBVTWsEvent@@@Z @ 10698 NONAME ABSENT ; int QApplicationPrivate::symbianProcessWsEvent(class TWsEvent const *) + ?symbianResourceChange@QApplicationPrivate@@QAEHH@Z @ 10699 NONAME ABSENT ; int QApplicationPrivate::symbianResourceChange(int) ?symbol@Parser@QCss@@QBEABUSymbol@2@XZ @ 10700 NONAME ; struct QCss::Symbol const & QCss::Parser::symbol(void) const ?sync@QPaintEngineEx@@UAEXXZ @ 10701 NONAME ; void QPaintEngineEx::sync(void) ?syncBackingStore@QWidgetPrivate@@QAEXABVQRegion@@@Z @ 10702 NONAME ; void QWidgetPrivate::syncBackingStore(class QRegion const &) @@ -12525,4 +12525,12 @@ EXPORTS ??0Tab@QTextOption@@QAE@ABU01@@Z @ 12524 NONAME ; QTextOption::Tab::Tab(struct QTextOption::Tab const &) ?effectiveBoundingRect@QGraphicsItemPrivate@@QBE?AVQRectF@@ABV2@@Z @ 12525 NONAME ; class QRectF QGraphicsItemPrivate::effectiveBoundingRect(class QRectF const &) const ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@PAXW4Type@2@ABVQTransform@@@Z @ 12526 NONAME ; class QFontEngineGlyphCache * QFontEngine::glyphCache(void *, enum QFontEngineGlyphCache::Type, class QTransform const &) const + ?qt_blurImage@@YAXAAVQImage@@M_NH@Z @ 12527 NONAME ; void qt_blurImage(class QImage &, float, bool, int) + ?qt_blurImage@@YAXPAVQPainter@@AAVQImage@@M_N2H@Z @ 12528 NONAME ; void qt_blurImage(class QPainter *, class QImage &, float, bool, bool, int) + ?qt_halfScaled@@YA?AVQImage@@ABV1@@Z @ 12529 NONAME ; class QImage qt_halfScaled(class QImage const &) + ?qt_memrotate90@@YAXPBIHHHPAIH@Z @ 12530 NONAME ; void qt_memrotate90(unsigned int const *, int, int, int, unsigned int *, int) + ?qt_memrotate90_gl@@YAXPBIHHHPAIH@Z @ 12531 NONAME ; void qt_memrotate90_gl(unsigned int const *, int, int, int, unsigned int *, int) + ?symbianHandleCommand@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12532 NONAME ; int QApplicationPrivate::symbianHandleCommand(class QSymbianEvent const *) + ?symbianProcessWsEvent@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12533 NONAME ; int QApplicationPrivate::symbianProcessWsEvent(class QSymbianEvent const *) + ?symbianResourceChange@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12534 NONAME ; int QApplicationPrivate::symbianResourceChange(class QSymbianEvent const *) diff --git a/src/s60installs/bwins/QtScriptu.def b/src/s60installs/bwins/QtScriptu.def index 8b53524..19f7037 100644 --- a/src/s60installs/bwins/QtScriptu.def +++ b/src/s60installs/bwins/QtScriptu.def @@ -369,4 +369,5 @@ EXPORTS ?willExecuteProgram@QScriptEngineAgentPrivate@@UAEXABVDebuggerCallFrame@QTJSC@@HH@Z @ 368 NONAME ; void QScriptEngineAgentPrivate::willExecuteProgram(class QTJSC::DebuggerCallFrame const &, int, int) ?staticMetaObject@QScriptExtensionPlugin@@2UQMetaObject@@B @ 369 NONAME ; struct QMetaObject const QScriptExtensionPlugin::staticMetaObject ?staticMetaObject@QScriptEngine@@2UQMetaObject@@B @ 370 NONAME ; struct QMetaObject const QScriptEngine::staticMetaObject + ?isQObject@QScriptDeclarativeClass@@UBE_NXZ @ 371 NONAME ; bool QScriptDeclarativeClass::isQObject(void) const diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 89fa76f..a427ff9 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3633,4 +3633,5 @@ EXPORTS _ZTIN13QStateMachine12WrappedEventE @ 3632 NONAME _ZTVN13QStateMachine11SignalEventE @ 3633 NONAME _ZTVN13QStateMachine12WrappedEventE @ 3634 NONAME + _ZN11QMetaObject13disconnectOneEPK7QObjectiS2_i @ 3635 NONAME diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index b6862e5..05f620c 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -11629,9 +11629,9 @@ EXPORTS _ZN18QTapAndHoldGestureC1EP7QObject @ 11628 NONAME _ZN18QTapAndHoldGestureC2EP7QObject @ 11629 NONAME _ZN19QAbstractScrollArea18setViewportMarginsERK8QMargins @ 11630 NONAME - _ZN19QApplicationPrivate20symbianHandleCommandEi @ 11631 NONAME - _ZN19QApplicationPrivate21symbianProcessWsEventEPK8TWsEvent @ 11632 NONAME - _ZN19QApplicationPrivate21symbianResourceChangeEi @ 11633 NONAME + _ZN19QApplicationPrivate20symbianHandleCommandEi @ 11631 NONAME ABSENT + _ZN19QApplicationPrivate21symbianProcessWsEventEPK8TWsEvent @ 11632 NONAME ABSENT + _ZN19QApplicationPrivate21symbianResourceChangeEi @ 11633 NONAME ABSENT _ZN19QGraphicsBlurEffect12setBlurHintsE6QFlagsINS_8BlurHintEE @ 11634 NONAME _ZN19QGraphicsBlurEffect13setBlurRadiusEf @ 11635 NONAME _ZN19QGraphicsBlurEffect16blurHintsChangedE6QFlagsINS_8BlurHintEE @ 11636 NONAME @@ -11784,4 +11784,12 @@ EXPORTS _ZNK14QEglProperties8toStringEv @ 11783 NONAME ABSENT _ZNK11QFontEngine10glyphCacheEPvN21QFontEngineGlyphCache4TypeERK10QTransform @ 11784 NONAME _ZNK20QGraphicsItemPrivate21effectiveBoundingRectERK6QRectF @ 11785 NONAME + _Z12qt_blurImageP8QPainterR6QImagefbbi @ 11786 NONAME + _Z12qt_blurImageR6QImagefbi @ 11787 NONAME + _Z13qt_halfScaledRK6QImage @ 11788 NONAME + _Z14qt_memrotate90PKjiiiPji @ 11789 NONAME + _Z17qt_memrotate90_glPKjiiiPji @ 11790 NONAME + _ZN19QApplicationPrivate20symbianHandleCommandEPK13QSymbianEvent @ 11791 NONAME + _ZN19QApplicationPrivate21symbianProcessWsEventEPK13QSymbianEvent @ 11792 NONAME + _ZN19QApplicationPrivate21symbianResourceChangeEPK13QSymbianEvent @ 11793 NONAME diff --git a/src/s60installs/eabi/QtScriptu.def b/src/s60installs/eabi/QtScriptu.def index 8df03c2..8a4be2c 100644 --- a/src/s60installs/eabi/QtScriptu.def +++ b/src/s60installs/eabi/QtScriptu.def @@ -393,4 +393,5 @@ EXPORTS _ZNK23QScriptDeclarativeClass7contextEv @ 392 NONAME _ZTI23QScriptDeclarativeClass @ 393 NONAME _ZTV23QScriptDeclarativeClass @ 394 NONAME + _ZNK23QScriptDeclarativeClass9isQObjectEv @ 395 NONAME diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby index f24ac4b..bdd668c 100644 --- a/src/s60installs/qt.iby +++ b/src/s60installs/qt.iby @@ -90,27 +90,27 @@ file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll S60_APP_RESOURCE(s60main) // imageformats stubs -data=\epoc32\data\qt\qtlibspluginstubs\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin +data=\epoc32\data\z\resource\qt\plugins\imageformats\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin // codecs stubs -data=\epoc32\data\qt\qtlibspluginstubs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin -data=\epoc32\data\qt\qtlibspluginstubs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin +data=\epoc32\data\z\resource\qt\plugins\codecs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin +data=\epoc32\data\z\resource\qt\plugins\codecs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin +data=\epoc32\data\z\resource\qt\plugins\codecs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin +data=\epoc32\data\z\resource\qt\plugins\codecs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin // iconengines stubs -data=\epoc32\data\qt\qtlibspluginstubs\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin +data=\epoc32\data\z\resource\qt\plugins\iconengines\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin // Phonon MMF backend -data=\epoc32\data\qt\qtlibspluginstubs\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin +data=\epoc32\data\z\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin // graphicssystems -data=\epoc32\data\qt\qtlibspluginstubs\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin +data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin // Stub sis file data=ZSYSTEM\install\qt.sis System\Install\qt.sis diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index bbc758b..aaecf6c 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -78,7 +78,11 @@ symbian: { DEPLOYMENT += phonon_backend_plugins } - DEPLOYMENT += qtresources qtlibraries imageformats_plugins codecs_plugins graphicssystems_plugins + # Support backup & restore for Qt libraries + qtbackup.sources = backup_registration.xml + qtbackup.path = c:/private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,) + + DEPLOYMENT += qtresources qtlibraries qtbackup imageformats_plugins codecs_plugins graphicssystems_plugins contains(QT_CONFIG, svg): { qtlibraries.sources += QtSvg.dll @@ -112,9 +116,4 @@ symbian: { BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" BLD_INF_RULES.prj_exports += "qtdemoapps.iby $$CORE_APP_LAYER_IBY_EXPORT_PATH(qtdemoapps.iby)" - PLUGIN_STUBS = $$files(qmakepluginstubs/*) - for(STUB, PLUGIN_STUBS) { - STUB_FILENAME = $$basename(STUB) - BLD_INF_RULES.prj_exports += "qmakepluginstubs/$${STUB_FILENAME} /epoc32/data/qt/qtlibspluginstubs/$${STUB_FILENAME}" - } } diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 0df9a49..ce2fc23 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -90,6 +90,11 @@ QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value)); } +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value)); +} + QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value) { new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); @@ -120,12 +125,11 @@ QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value) new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value)); } -QScriptDeclarativeClass::Value::Value(const QScriptValue &value) +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value) { - new (this) JSC::JSValue(QScriptValuePrivate::get(&value)->engine->scriptValueToJSCValue(value)); + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value)); } - QScriptDeclarativeClass::Value::~Value() { ((JSC::JSValue *)(this))->~JSValue(); diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 6050971..357d1d5 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -52,7 +52,6 @@ public: public: Value(); Value(const Value &); - Value(const QScriptValue &); Value(QScriptContext *, int); Value(QScriptContext *, uint); @@ -60,12 +59,14 @@ public: Value(QScriptContext *, double); Value(QScriptContext *, float); Value(QScriptContext *, const QString &); + Value(QScriptContext *, const QScriptValue &); Value(QScriptEngine *, int); Value(QScriptEngine *, uint); Value(QScriptEngine *, bool); Value(QScriptEngine *, double); Value(QScriptEngine *, float); Value(QScriptEngine *, const QString &); + Value(QScriptEngine *, const QScriptValue &); ~Value(); QScriptValue toScriptValue(QScriptEngine *) const; diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index fb0dddb..db312bc 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -978,7 +978,8 @@ JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue, QScriptObjectDelegate *delegate = scriptObject->delegate(); Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); QObject *qobj = static_cast<QScript::QObjectDelegate*>(delegate)->value(); - Q_ASSERT_X(qobj != 0, "QtFunction::call", "handle the case when QObject has been deleted"); + if (!qobj) + return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("cannot call function of deleted QObject")); QScriptEnginePrivate *engine = scriptEngineFromExec(exec); const QMetaObject *meta = qobj->metaObject(); @@ -2219,7 +2220,14 @@ void QObjectConnectionManager::execute(int slotIndex, void **argv) JSC::call(exec, slot, callType, callData, thisObject, jscArgs); if (exec->hadException()) { - engine->emitSignalHandlerException(); + if (slot.inherits(&QtFunction::info) && !static_cast<QtFunction*>(JSC::asObject(slot))->qobject()) { + // The function threw an error because the target QObject has been deleted. + // The connections list is stale; remove the signal handler and ignore the exception. + removeSignalHandler(sender(), signalIndex, receiver, slot); + exec->clearException(); + } else { + engine->emitSignalHandlerException(); + } } } diff --git a/src/tools/uic3/converter.cpp b/src/tools/uic3/converter.cpp index 8fe2a24..2bf293d 100644 --- a/src/tools/uic3/converter.cpp +++ b/src/tools/uic3/converter.cpp @@ -121,7 +121,7 @@ static inline bool isKDEClass(const QString &className) return className.at(1) .isUpper() && className.at(2).isLower(); } -DomUI *Ui3Reader::generateUi4(const QDomElement &widget, bool implicitIncludes) +DomUI *Ui3Reader::generateUi4(const QDomElement &widget) { QDomNodeList nl; candidateCustomWidgets.clear(); @@ -474,7 +474,7 @@ DomUI *Ui3Reader::generateUi4(const QDomElement &widget, bool implicitIncludes) // Magic header generation feature for legacy KDE forms // (for example, filesharing/advanced/kcm_sambaconf/share.ui) - if (implicitIncludes && isKDEClass(customClass)) { + if ((m_options & ImplicitIncludes) && isKDEClass(customClass)) { QString header = customClass.toLower(); header += QLatin1String(".h"); DomHeader *domHeader = new DomHeader; @@ -710,10 +710,13 @@ DomWidget *Ui3Reader::createWidget(const QDomElement &w, const QString &widgetCl ui_action_list.append(a); } else if (t == QLatin1String("property")) { // skip the property it is already handled by createProperties - - QString name = e.attribute(QLatin1String("name")); // change the varname this widget - if (name == QLatin1String("name")) - ui_widget->setAttributeName(DomTool::readProperty(w, QLatin1String("name"), QVariant()).toString()); + const QString name = e.attribute(QLatin1String("name")); // change the varname this widget + if (name == QLatin1String("name")) { + // Do not name QLayoutWidget if layout names are to be used. + const bool applyName = !(m_options & PreserveLayoutNames) || className != QLatin1String("QLayoutWidget"); + if (applyName) + ui_widget->setAttributeName(DomTool::readProperty(w, QLatin1String("name"), QVariant()).toString()); + } } else if (t == QLatin1String("row")) { DomRow *row = new DomRow(); row->read(e); @@ -797,6 +800,11 @@ DomLayout *Ui3Reader::createLayout(const QDomElement &w) createProperties(w, &ui_property_list, className); createAttributes(w, &ui_attribute_list, className); + if (m_options & PreserveLayoutNames) { + const QString layoutName = getLayoutName(w); + if (!layoutName.isEmpty()) + lay->setAttributeName(layoutName); + } QDomElement e = w.firstChild().toElement(); while (!e.isNull()) { diff --git a/src/tools/uic3/form.cpp b/src/tools/uic3/form.cpp index ac2668b..df1314f 100644 --- a/src/tools/uic3/form.cpp +++ b/src/tools/uic3/form.cpp @@ -100,7 +100,7 @@ QByteArray combinePath(const char *infile, const char *outfile) \sa createFormImpl() */ -void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes) +void Ui3Reader::createFormDecl(const QDomElement &e) { QDomElement body = e; @@ -138,7 +138,7 @@ void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes) QString tagName = n3.tagName().toLower(); if (tagName == QLatin1String("class")) { cl = n3.firstChild().toText().data(); - if (!nofwd) + if (m_options & CustomWidgetForwardDeclarations) forwardDecl << cl; customWidgets.insert(cl, 0); } else if (tagName == QLatin1String("header")) { @@ -257,10 +257,10 @@ void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes) d.option().copyrightHeader = false; d.option().extractImages = m_extractImages; d.option().qrcOutputFile = m_qrcOutputFile; - d.option().implicitIncludes = implicitIncludes; + d.option().implicitIncludes = (m_options & ImplicitIncludes) ? 1 : 0; if (trmacro.size()) d.option().translateFunction = trmacro; - DomUI *ui = generateUi4(e, implicitIncludes); + DomUI *ui = generateUi4(e); d.uic(fileName, ui, &out); delete ui; diff --git a/src/tools/uic3/main.cpp b/src/tools/uic3/main.cpp index ecc345e..6acc94f 100644 --- a/src/tools/uic3/main.cpp +++ b/src/tools/uic3/main.cpp @@ -78,13 +78,11 @@ int runUic3(int argc, char * argv[]) QByteArray image_tmpfile; const char* projectName = 0; const char* trmacro = 0; - bool nofwd = false; bool fix = false; bool deps = false; - bool implicitIncludes = true; + unsigned readerOptions = Ui3Reader::ImplicitIncludes|Ui3Reader::CustomWidgetForwardDeclarations; QByteArray pchFile; - QApplication app(argc, argv, false); for (int n = 1; n < argc && error == 0; n++) { @@ -146,9 +144,11 @@ int runUic3(int argc, char * argv[]) } else if (opt == "d") { deps = true; } else if (opt == "no-implicit-includes") { - implicitIncludes = false; + readerOptions &= ~Ui3Reader::ImplicitIncludes; } else if (opt == "nofwd") { - nofwd = true; + readerOptions &= ~Ui3Reader::CustomWidgetForwardDeclarations; + } else if (opt == "layout-names") { + readerOptions |= Ui3Reader::PreserveLayoutNames; } else if (opt == "nounload") { // skip } else if (opt == "convert") { @@ -253,6 +253,7 @@ int runUic3(int argc, char * argv[]) "\t-extract qrcFile Create resource file and extract embedded images into \"image\" dir\n" "\t-pch file Add #include \"file\" as the first statement in implementation\n" "\t-nofwd Omit forward declarations of custom classes\n" + "\t-layout-names Preserve layout names of Qt Designer 3\n" "\t-no-implicit-includes Do not generate #include-directives for custom classes\n" "\t-nounload Do not unload plugins after processing\n" "\t-tr func Use func() instead of tr() for i18n\n" @@ -289,9 +290,8 @@ int runUic3(int argc, char * argv[]) QTextStream out(&fileOut); - Ui3Reader ui3(out); + Ui3Reader ui3(out, readerOptions); ui3.setExtractImages(extract, qrcOutputFile); - if (projectName && imagecollection) { out.setEncoding(QTextStream::Latin1); ui3.embed(projectName, images); @@ -349,7 +349,7 @@ int runUic3(int argc, char * argv[]) return 0; } else if (convert) { - ui3.generateUi4(QFile::decodeName(fileName), QFile::decodeName(outputFile), doc, implicitIncludes); + ui3.generateUi4(QFile::decodeName(fileName), QFile::decodeName(outputFile), doc); return 0; } @@ -388,8 +388,6 @@ int runUic3(int argc, char * argv[]) subcl, QString::fromUtf8(trmacro), QString::fromUtf8(className), - nofwd, - implicitIncludes, convertedUi); if (!protector.isEmpty()) { diff --git a/src/tools/uic3/ui3reader.cpp b/src/tools/uic3/ui3reader.cpp index 6c5bda3..fd50a19 100644 --- a/src/tools/uic3/ui3reader.cpp +++ b/src/tools/uic3/ui3reader.cpp @@ -176,7 +176,6 @@ void Ui3Reader::init() { outputFileName.clear(); trmacro.clear(); - nofwd = false; fileName.clear(); writeFunctImpl = true; @@ -241,11 +240,10 @@ QDomElement Ui3Reader::parse(const QDomDocument &doc) return widget; } -Ui3Reader::Ui3Reader(QTextStream &outStream) - : out(outStream), trout(&languageChangeBody) +Ui3Reader::Ui3Reader(QTextStream &outStream, unsigned options) : + m_options(options), out(outStream), trout(&languageChangeBody), + m_porting(new Porting), m_extractImages(false) { - m_porting = new Porting(); - m_extractImages = false; } Ui3Reader::~Ui3Reader() @@ -255,14 +253,13 @@ Ui3Reader::~Ui3Reader() void Ui3Reader::generate(const QString &fn, const QString &outputFn, QDomDocument doc, bool decl, bool subcl, const QString &trm, - const QString& subClass, bool omitForwardDecls, bool implicitIncludes, const QString &convertedUiFile) + const QString& subClass, const QString &convertedUiFile) { init(); fileName = fn; outputFileName = outputFn; trmacro = trm; - nofwd = omitForwardDecls; QDomElement e = parse(doc); @@ -281,21 +278,21 @@ void Ui3Reader::generate(const QString &fn, const QString &outputFn, createSubImpl(e, subClass); } else { if (decl) - createFormDecl(e, implicitIncludes); + createFormDecl(e); else createFormImpl(e); } } -void Ui3Reader::generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc, bool implicitIncludes) +void Ui3Reader::generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc) { init(); fileName = fn; outputFileName = outputFn; - DomUI *ui = generateUi4(parse(doc), implicitIncludes); + DomUI *ui = generateUi4(parse(doc)); if (!ui) return; @@ -317,11 +314,6 @@ void Ui3Reader::setTrMacro(const QString &trmacro) this->trmacro = trmacro; } -void Ui3Reader::setForwardDeclarationsEnabled(bool b) -{ - nofwd = !b; -} - void Ui3Reader::setOutputFileName(const QString &fileName) { outputFileName = fileName; diff --git a/src/tools/uic3/ui3reader.h b/src/tools/uic3/ui3reader.h index cd17835..144ef05 100644 --- a/src/tools/uic3/ui3reader.h +++ b/src/tools/uic3/ui3reader.h @@ -68,23 +68,24 @@ typedef QList<QPair<int, Color> > ColorGroup; class Ui3Reader { public: - Ui3Reader(QTextStream &stream); + enum Options { CustomWidgetForwardDeclarations = 0x1, ImplicitIncludes = 0x2, PreserveLayoutNames = 0x4 }; + + explicit Ui3Reader(QTextStream &stream, unsigned options); ~Ui3Reader(); void computeDeps(const QDomElement &e, QStringList &globalIncludes, QStringList &localIncludes, bool impl = false); - void generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc, bool implicitIncludes); + void generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc); void generate(const QString &fn, const QString &outputFn, QDomDocument doc, bool decl, bool subcl, const QString &trm, - const QString& subclname, bool omitForwardDecls, bool implicitIncludes, const QString &convertedUiFile); + const QString& subclname, const QString &convertedUiFile); void embed(const char *project, const QStringList &images); void setTrMacro(const QString &trmacro); - void setForwardDeclarationsEnabled(bool b); void setOutputFileName(const QString &fileName); - void createFormDecl(const QDomElement &e, bool implicitIncludes); + void createFormDecl(const QDomElement &e); void createFormImpl(const QDomElement &e); void createWrapperDecl(const QDomElement &e, const QString &convertedUiFile); @@ -125,7 +126,7 @@ private: void errorInvalidSlot(const QString &slot, const QString &widgetName, const QString &widgetClass, int line, int col); - DomUI *generateUi4(const QDomElement &e, bool implicitIncludes); + DomUI *generateUi4(const QDomElement &e); DomWidget *createWidget(const QDomElement &w, const QString &widgetClass = QString()); void createProperties(const QDomElement &e, QList<DomProperty*> *properties, const QString &className); void createAttributes(const QDomElement &e, QList<DomProperty*> *properties, const QString &className); @@ -145,6 +146,8 @@ private: void fixLayoutMargin(DomLayout *ui_layout); + const unsigned m_options; + QTextStream &out; QTextOStream trout; QString languageChangeBody; @@ -157,7 +160,6 @@ private: QString formName; QString lastItem; QString trmacro; - bool nofwd; struct Buddy { diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 657c79a..cae959b 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -2596,11 +2596,15 @@ QDomNode QDomNode::removeChild(const QDomNode& oldChild) already has an element node as a child, \a newChild is not added as a child and a null node is returned. - Calling this function on a null node(created, for example, with the - default constructor) does nothing. + Returns a new reference to \a newChild on success or a \link + isNull() null node\endlink on failure. - The DOM specification disallow inserting attribute nodes, but due - to historical reasons QDom accept them nevertheless. + Calling this function on a null node(created, for example, with + the default constructor) does nothing and returns a \link isNull() + null node\endlink. + + The DOM specification disallow inserting attribute nodes, but for + historical reasons, QDom accepts them anyway. \sa insertBefore() insertAfter() replaceChild() removeChild() */ diff --git a/src/xmlpatterns/parser/qquerytransformparser.cpp b/src/xmlpatterns/parser/qquerytransformparser.cpp index c250d0c..6daa470 100644 --- a/src/xmlpatterns/parser/qquerytransformparser.cpp +++ b/src/xmlpatterns/parser/qquerytransformparser.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/xmlpatterns/parser/qquerytransformparser_p.h b/src/xmlpatterns/parser/qquerytransformparser_p.h index 204b6f8..0b316ec 100644 --- a/src/xmlpatterns/parser/qquerytransformparser_p.h +++ b/src/xmlpatterns/parser/qquerytransformparser_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/xmlpatterns/parser/qxslttokenlookup.cpp b/src/xmlpatterns/parser/qxslttokenlookup.cpp index a46ec8a..781ba0d 100644 --- a/src/xmlpatterns/parser/qxslttokenlookup.cpp +++ b/src/xmlpatterns/parser/qxslttokenlookup.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/xmlpatterns/parser/qxslttokenlookup_p.h b/src/xmlpatterns/parser/qxslttokenlookup_p.h index b45407d..6d004b0 100644 --- a/src/xmlpatterns/parser/qxslttokenlookup_p.h +++ b/src/xmlpatterns/parser/qxslttokenlookup_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** |