aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/context2d/qquickcanvascontext_p.h4
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp5
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h4
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp51
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h6
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h4
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h4
-rw-r--r--src/quick/items/context2d/qquickcontext2dtile_p.h4
-rw-r--r--src/quick/items/items.pri19
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h4
-rw-r--r--src/quick/items/qquickanchors_p.h4
-rw-r--r--src/quick/items/qquickanimatedimage_p.h4
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp4
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h4
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickdrag_p.h4
-rw-r--r--src/quick/items/qquickdroparea_p.h4
-rw-r--r--src/quick/items/qquickflickable.cpp39
-rw-r--r--src/quick/items/qquickflickable_p.h4
-rw-r--r--src/quick/items/qquickflipable_p.h4
-rw-r--r--src/quick/items/qquickfocusscope_p.h4
-rw-r--r--src/quick/items/qquickgridview.cpp23
-rw-r--r--src/quick/items/qquickgridview_p.h7
-rw-r--r--src/quick/items/qquickimage_p.h4
-rw-r--r--src/quick/items/qquickimagebase_p.h4
-rw-r--r--src/quick/items/qquickimplicitsizeitem.cpp6
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p.h12
-rw-r--r--src/quick/items/qquickitem.cpp273
-rw-r--r--src/quick/items/qquickitem.h11
-rw-r--r--src/quick/items/qquickitem_p.h27
-rw-r--r--src/quick/items/qquickitemanimation_p.h4
-rw-r--r--src/quick/items/qquickitemsmodule.cpp14
-rw-r--r--src/quick/items/qquickitemsmodule_p.h4
-rw-r--r--src/quick/items/qquickitemview.cpp120
-rw-r--r--src/quick/items/qquickitemview_p.h14
-rw-r--r--src/quick/items/qquickitemview_p_p.h33
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h4
-rw-r--r--src/quick/items/qquicklistview.cpp25
-rw-r--r--src/quick/items/qquicklistview_p.h8
-rw-r--r--src/quick/items/qquickloader.cpp70
-rw-r--r--src/quick/items/qquickloader_p.h4
-rw-r--r--src/quick/items/qquickmousearea.cpp50
-rw-r--r--src/quick/items/qquickmousearea_p.h4
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h4
-rw-r--r--src/quick/items/qquickpainteditem.h4
-rw-r--r--src/quick/items/qquickpathview.cpp84
-rw-r--r--src/quick/items/qquickpathview_p.h13
-rw-r--r--src/quick/items/qquickpathview_p_p.h5
-rw-r--r--src/quick/items/qquickpincharea_p.h4
-rw-r--r--src/quick/items/qquickpositioners.cpp115
-rw-r--r--src/quick/items/qquickpositioners_p.h28
-rw-r--r--src/quick/items/qquickrectangle.cpp2
-rw-r--r--src/quick/items/qquickrectangle_p.h4
-rw-r--r--src/quick/items/qquickrepeater.cpp82
-rw-r--r--src/quick/items/qquickrepeater_p.h12
-rw-r--r--src/quick/items/qquickrepeater_p_p.h5
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h4
-rw-r--r--src/quick/items/qquickscreen.cpp50
-rw-r--r--src/quick/items/qquickscreen_p.h4
-rw-r--r--src/quick/items/qquickshadereffect_p.h4
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h4
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h4
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp13
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h7
-rw-r--r--src/quick/items/qquicksprite.cpp11
-rw-r--r--src/quick/items/qquicksprite_p.h3
-rw-r--r--src/quick/items/qquickspriteengine.cpp3
-rw-r--r--src/quick/items/qquickspriteengine_p.h4
-rw-r--r--src/quick/items/qquickspritesequence_p.h4
-rw-r--r--src/quick/items/qquickstateoperations_p.h4
-rw-r--r--src/quick/items/qquicktext.cpp4
-rw-r--r--src/quick/items/qquicktext_p.h4
-rw-r--r--src/quick/items/qquicktextcontrol.cpp37
-rw-r--r--src/quick/items/qquicktextcontrol_p.h5
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h10
-rw-r--r--src/quick/items/qquicktextdocument.cpp (renamed from src/quick/items/qquickwindowmanager_p.h)56
-rw-r--r--src/quick/items/qquicktextdocument.h86
-rw-r--r--src/quick/items/qquicktextedit.cpp487
-rw-r--r--src/quick/items/qquicktextedit_p.h23
-rw-r--r--src/quick/items/qquicktextedit_p_p.h38
-rw-r--r--src/quick/items/qquicktextinput.cpp63
-rw-r--r--src/quick/items/qquicktextinput_p.h6
-rw-r--r--src/quick/items/qquicktextinput_p_p.h2
-rw-r--r--src/quick/items/qquicktextnode.cpp1129
-rw-r--r--src/quick/items/qquicktextnode_p.h9
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp935
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h234
-rw-r--r--src/quick/items/qquickthreadedwindowmanager.cpp910
-rw-r--r--src/quick/items/qquickthreadedwindowmanager_p.h181
-rw-r--r--src/quick/items/qquicktranslate_p.h4
-rw-r--r--src/quick/items/qquickview.cpp2
-rw-r--r--src/quick/items/qquickview.h4
-rw-r--r--src/quick/items/qquickview_p.h4
-rw-r--r--src/quick/items/qquickvisualadaptormodel.cpp977
-rw-r--r--src/quick/items/qquickvisualadaptormodel_p.h156
-rw-r--r--src/quick/items/qquickvisualdatamodel.cpp3173
-rw-r--r--src/quick/items/qquickvisualdatamodel_p.h238
-rw-r--r--src/quick/items/qquickvisualdatamodel_p_p.h411
-rw-r--r--src/quick/items/qquickvisualitemmodel.cpp256
-rw-r--r--src/quick/items/qquickvisualitemmodel_p.h174
-rw-r--r--src/quick/items/qquickwindow.cpp270
-rw-r--r--src/quick/items/qquickwindow.h6
-rw-r--r--src/quick/items/qquickwindow_p.h8
-rw-r--r--src/quick/items/qquickwindowmanager.cpp363
-rw-r--r--src/quick/items/qquickwindowmodule.cpp2
-rw-r--r--src/quick/items/qquickwindowmodule_p.h4
106 files changed, 2847 insertions, 8808 deletions
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h
index bfea0e5d5b..d15f5d945d 100644
--- a/src/quick/items/context2d/qquickcanvascontext_p.h
+++ b/src/quick/items/context2d/qquickcanvascontext_p.h
@@ -46,8 +46,6 @@
#include <private/qv8engine_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickCanvasItem;
@@ -83,6 +81,4 @@ Q_SIGNALS:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif //QQUICKCANVASCONTEXT_P_H
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 7c91193623..9d9ddd6ef0 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -190,9 +190,10 @@ QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
, hasCanvasWindow(false)
, available(false)
, contextInitialized(false)
- , renderTarget(QQuickCanvasItem::FramebufferObject)
+ , renderTarget(QQuickCanvasItem::Image)
, renderStrategy(QQuickCanvasItem::Cooperative)
{
+ antialiasing = true;
}
QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
@@ -245,7 +246,7 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
results in faster rendering.
The default render target is Canvas.Image and the default renderStrategy is
- Canvas.Threaded.
+ Canvas.Cooperative.
\section1 Tiled Canvas
The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index d2a907554e..c53e4f952a 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -47,8 +47,6 @@
#include <QtCore/QThread>
#include <QtGui/QImage>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickCanvasContext;
@@ -207,6 +205,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickCanvasItem)
-QT_END_HEADER
-
#endif //QQUICKCANVASITEM_P_H
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 2f37c7f109..995d951a8a 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -62,9 +62,8 @@
#include <private/qv8domerrors_p.h>
#include <QtCore/qnumeric.h>
#include <private/qquickwindow_p.h>
-#include <private/qquickwindowmanager_p.h>
-#if defined(Q_OS_QNX) || defined(Q_OS_LINUX_ANDROID)
+#if defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
#include <ctype.h>
#endif
@@ -3348,7 +3347,6 @@ QQuickContext2D::QQuickContext2D(QObject *parent)
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
, m_v8engine(0)
- , m_windowManager(0)
, m_surface(0)
, m_glContext(0)
, m_thread(0)
@@ -3380,7 +3378,6 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
m_renderTarget = canvasItem->renderTarget();
QQuickWindow *window = canvasItem->window();
- m_windowManager = QQuickWindowPrivate::get(window)->windowManager;
m_renderStrategy = canvasItem->renderStrategy();
switch (m_renderTarget) {
@@ -3482,7 +3479,7 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
ft->InstanceTemplate()->SetHasExternalResource(true);
- ft->PrototypeTemplate()->SetAccessor(v8::String::New("canvas"), ctx2d_canvas, 0, v8::External::Wrap(engine));
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("canvas"), ctx2d_canvas, 0, v8::External::New(engine));
ft->PrototypeTemplate()->Set(v8::String::New("restore"), V8FUNCTION(ctx2d_restore, engine));
ft->PrototypeTemplate()->Set(v8::String::New("reset"), V8FUNCTION(ctx2d_reset, engine));
ft->PrototypeTemplate()->Set(v8::String::New("save"), V8FUNCTION(ctx2d_save, engine));
@@ -3493,24 +3490,24 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
ft->PrototypeTemplate()->Set(v8::String::New("transform"), V8FUNCTION(ctx2d_transform, engine));
ft->PrototypeTemplate()->Set(v8::String::New("translate"), V8FUNCTION(ctx2d_translate, engine));
ft->PrototypeTemplate()->Set(v8::String::New("shear"), V8FUNCTION(ctx2d_shear, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("globalAlpha"), ctx2d_globalAlpha, ctx2d_globalAlpha_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("globalCompositeOperation"), ctx2d_globalCompositeOperation, ctx2d_globalCompositeOperation_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("fillRule"), ctx2d_fillRule, ctx2d_fillRule_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("fillStyle"), ctx2d_fillStyle, ctx2d_fillStyle_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("strokeStyle"), ctx2d_strokeStyle, ctx2d_strokeStyle_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("globalAlpha"), ctx2d_globalAlpha, ctx2d_globalAlpha_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("globalCompositeOperation"), ctx2d_globalCompositeOperation, ctx2d_globalCompositeOperation_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("fillRule"), ctx2d_fillRule, ctx2d_fillRule_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("fillStyle"), ctx2d_fillStyle, ctx2d_fillStyle_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("strokeStyle"), ctx2d_strokeStyle, ctx2d_strokeStyle_set, v8::External::New(engine));
ft->PrototypeTemplate()->Set(v8::String::New("createLinearGradient"), V8FUNCTION(ctx2d_createLinearGradient, engine));
ft->PrototypeTemplate()->Set(v8::String::New("createRadialGradient"), V8FUNCTION(ctx2d_createRadialGradient, engine));
ft->PrototypeTemplate()->Set(v8::String::New("createConicalGradient"), V8FUNCTION(ctx2d_createConicalGradient, engine));
ft->PrototypeTemplate()->Set(v8::String::New("createPattern"), V8FUNCTION(ctx2d_createPattern, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineCap"), ctx2d_lineCap, ctx2d_lineCap_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineJoin"), ctx2d_lineJoin, ctx2d_lineJoin_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineWidth"), ctx2d_lineWidth, ctx2d_lineWidth_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("miterLimit"), ctx2d_miterLimit, ctx2d_miterLimit_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowBlur"), ctx2d_shadowBlur, ctx2d_shadowBlur_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowColor"), ctx2d_shadowColor, ctx2d_shadowColor_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetX"), ctx2d_shadowOffsetX, ctx2d_shadowOffsetX_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetY"), ctx2d_shadowOffsetY, ctx2d_shadowOffsetY_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("path"), ctx2d_path, ctx2d_path_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineCap"), ctx2d_lineCap, ctx2d_lineCap_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineJoin"), ctx2d_lineJoin, ctx2d_lineJoin_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineWidth"), ctx2d_lineWidth, ctx2d_lineWidth_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("miterLimit"), ctx2d_miterLimit, ctx2d_miterLimit_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowBlur"), ctx2d_shadowBlur, ctx2d_shadowBlur_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowColor"), ctx2d_shadowColor, ctx2d_shadowColor_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetX"), ctx2d_shadowOffsetX, ctx2d_shadowOffsetX_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetY"), ctx2d_shadowOffsetY, ctx2d_shadowOffsetY_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("path"), ctx2d_path, ctx2d_path_set, v8::External::New(engine));
ft->PrototypeTemplate()->Set(v8::String::New("clearRect"), V8FUNCTION(ctx2d_clearRect, engine));
ft->PrototypeTemplate()->Set(v8::String::New("fillRect"), V8FUNCTION(ctx2d_fillRect, engine));
ft->PrototypeTemplate()->Set(v8::String::New("strokeRect"), V8FUNCTION(ctx2d_strokeRect, engine));
@@ -3533,9 +3530,9 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
ft->PrototypeTemplate()->Set(v8::String::New("drawFocusRing"), V8FUNCTION(ctx2d_drawFocusRing, engine));
ft->PrototypeTemplate()->Set(v8::String::New("caretBlinkRate"), V8FUNCTION(ctx2d_caretBlinkRate, engine));
ft->PrototypeTemplate()->Set(v8::String::New("setCaretSelectionRect"), V8FUNCTION(ctx2d_setCaretSelectionRect, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("font"), ctx2d_font, ctx2d_font_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("textAlign"), ctx2d_textAlign, ctx2d_textAlign_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("textBaseline"), ctx2d_textBaseline, ctx2d_textBaseline_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("font"), ctx2d_font, ctx2d_font_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("textAlign"), ctx2d_textAlign, ctx2d_textAlign_set, v8::External::New(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("textBaseline"), ctx2d_textBaseline, ctx2d_textBaseline_set, v8::External::New(engine));
ft->PrototypeTemplate()->Set(v8::String::New("fillText"), V8FUNCTION(ctx2d_fillText, engine));
ft->PrototypeTemplate()->Set(v8::String::New("measureText"), V8FUNCTION(ctx2d_measureText, engine));
ft->PrototypeTemplate()->Set(v8::String::New("strokeText"), V8FUNCTION(ctx2d_strokeText, engine));
@@ -3557,14 +3554,14 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
v8::Local<v8::FunctionTemplate> ftPixelArray = v8::FunctionTemplate::New();
ftPixelArray->InstanceTemplate()->SetHasExternalResource(true);
- ftPixelArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), ctx2d_pixelArray_length, 0, v8::External::Wrap(engine));
- ftPixelArray->InstanceTemplate()->SetIndexedPropertyHandler(ctx2d_pixelArray_indexed, ctx2d_pixelArray_indexed_set, 0, 0, 0, v8::External::Wrap(engine));
+ ftPixelArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), ctx2d_pixelArray_length, 0, v8::External::New(engine));
+ ftPixelArray->InstanceTemplate()->SetIndexedPropertyHandler(ctx2d_pixelArray_indexed, ctx2d_pixelArray_indexed_set, 0, 0, 0, v8::External::New(engine));
constructorPixelArray = qPersistentNew(ftPixelArray->GetFunction());
v8::Local<v8::FunctionTemplate> ftImageData = v8::FunctionTemplate::New();
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("width"), ctx2d_imageData_width, 0, v8::External::Wrap(engine));
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("height"), ctx2d_imageData_height, 0, v8::External::Wrap(engine));
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("data"), ctx2d_imageData_data, 0, v8::External::Wrap(engine));
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("width"), ctx2d_imageData_width, 0, v8::External::New(engine));
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("height"), ctx2d_imageData_height, 0, v8::External::New(engine));
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("data"), ctx2d_imageData_data, 0, v8::External::New(engine));
ftImageData->InstanceTemplate()->SetInternalFieldCount(1);
constructorImageData = qPersistentNew(ftImageData->GetFunction());
}
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 2124c731b2..24f5c44f18 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -62,15 +62,12 @@
#include <QElapsedTimer>
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickContext2DCommandBuffer;
class QQuickContext2DTexture;
class QQuickPixmap;
class QSGTexture;
-class QQuickWindowManager;
class QSurface;
class QOpenGLContext;
@@ -240,7 +237,6 @@ public:
v8::Local<v8::Value> m_strokeStyle;
v8::Handle<v8::Value> m_v8path;
QV8Engine *m_v8engine;
- QQuickWindowManager *m_windowManager;
QSurface *m_surface;
QOpenGLContext *m_glContext;
v8::Persistent<v8::Object> m_v8value;
@@ -259,6 +255,4 @@ public:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickContext2D)
-QT_END_HEADER
-
#endif // QQUICKCONTEXT2D_P_H
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index 0247a9e286..ff0a3a4e20 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -45,8 +45,6 @@
#include <QtCore/qmutex.h>
#include "qquickcontext2d_p.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickCanvasItem;
@@ -266,8 +264,6 @@ private:
QMutex queueLock;
};
-QT_END_HEADER
-
QT_END_NAMESPACE
#endif // QQUICKCONTEXT2DCOMMANDBUFFER_P_H
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index 8fe3168533..df96a0eda1 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -53,8 +53,6 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QThread>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickContext2DTile;
@@ -180,8 +178,6 @@ private:
QSGPlainTexture* m_texture;
};
-QT_END_HEADER
-
QT_END_NAMESPACE
#endif // QQUICKCONTEXT2DTEXTURE_P_H
diff --git a/src/quick/items/context2d/qquickcontext2dtile_p.h b/src/quick/items/context2d/qquickcontext2dtile_p.h
index 60415ee63d..22cbbe6a30 100644
--- a/src/quick/items/context2d/qquickcontext2dtile_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtile_p.h
@@ -45,8 +45,6 @@
#include "qquickcontext2d_p.h"
#include <QOpenGLFramebufferObject>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickContext2DTexture;
@@ -103,8 +101,6 @@ public:
private:
QImage m_image;
};
-QT_END_HEADER
-
QT_END_NAMESPACE
#endif // QQUICKCONTEXT2DTILE_P_H
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 13abf7b958..5aaf7d3ac6 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -17,10 +17,12 @@ HEADERS += \
$$PWD/qquicktext_p.h \
$$PWD/qquicktext_p_p.h \
$$PWD/qquicktextnode_p.h \
+ $$PWD/qquicktextnodeengine_p.h \
$$PWD/qquicktextinput_p.h \
$$PWD/qquicktextinput_p_p.h \
$$PWD/qquicktextcontrol_p.h \
$$PWD/qquicktextcontrol_p_p.h \
+ $$PWD/qquicktextdocument.h \
$$PWD/qquicktextedit_p.h \
$$PWD/qquicktextedit_p_p.h \
$$PWD/qquicktextutil_p.h \
@@ -38,10 +40,6 @@ HEADERS += \
$$PWD/qquickflickable_p.h \
$$PWD/qquickflickable_p_p.h \
$$PWD/qquicklistview_p.h \
- $$PWD/qquickvisualadaptormodel_p.h \
- $$PWD/qquickvisualdatamodel_p.h \
- $$PWD/qquickvisualdatamodel_p_p.h \
- $$PWD/qquickvisualitemmodel_p.h \
$$PWD/qquickrepeater_p.h \
$$PWD/qquickrepeater_p_p.h \
$$PWD/qquickgridview_p.h \
@@ -74,9 +72,7 @@ HEADERS += \
$$PWD/qquickitemview_p_p.h \
$$PWD/qquickitemviewtransition_p.h \
$$PWD/qquickscreen_p.h \
- $$PWD/qquickwindowmodule_p.h \
- $$PWD/qquickwindowmanager_p.h \
- $$PWD/qquickthreadedwindowmanager_p.h
+ $$PWD/qquickwindowmodule_p.h
SOURCES += \
$$PWD/qquickevents.cpp \
@@ -89,8 +85,10 @@ SOURCES += \
$$PWD/qquickpainteditem.cpp \
$$PWD/qquicktext.cpp \
$$PWD/qquicktextnode.cpp \
+ $$PWD/qquicktextnodeengine.cpp \
$$PWD/qquicktextinput.cpp \
$$PWD/qquicktextcontrol.cpp \
+ $$PWD/qquicktextdocument.cpp \
$$PWD/qquicktextedit.cpp \
$$PWD/qquicktextutil.cpp \
$$PWD/qquickimagebase.cpp \
@@ -101,9 +99,6 @@ SOURCES += \
$$PWD/qquickpincharea.cpp \
$$PWD/qquickflickable.cpp \
$$PWD/qquicklistview.cpp \
- $$PWD/qquickvisualadaptormodel.cpp \
- $$PWD/qquickvisualdatamodel.cpp \
- $$PWD/qquickvisualitemmodel.cpp \
$$PWD/qquickrepeater.cpp \
$$PWD/qquickgridview.cpp \
$$PWD/qquickpathview.cpp \
@@ -128,9 +123,7 @@ SOURCES += \
$$PWD/qquickitemview.cpp \
$$PWD/qquickitemviewtransition.cpp \
$$PWD/qquickwindowmodule.cpp \
- $$PWD/qquickscreen.cpp \
- $$PWD/qquickwindowmanager.cpp \
- $$PWD/qquickthreadedwindowmanager.cpp
+ $$PWD/qquickscreen.cpp
SOURCES += \
$$PWD/qquickshadereffect.cpp \
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index 15261232b2..2124356a70 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -52,8 +52,6 @@
#include <QtGui/qaccessible.h>
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -165,8 +163,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickAccessibleAttached)
QML_DECLARE_TYPEINFO(QQuickAccessibleAttached, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
#endif // QT_NO_ACCESSIBILITY
#endif
diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h
index df3577c42d..1f18961caf 100644
--- a/src/quick/items/qquickanchors_p.h
+++ b/src/quick/items/qquickanchors_p.h
@@ -48,8 +48,6 @@
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -200,6 +198,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickAnchors)
-QT_END_HEADER
-
#endif // QQUICKANCHORS_P_H
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
index 83bae59af8..2775023d4e 100644
--- a/src/quick/items/qquickanimatedimage_p.h
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -46,8 +46,6 @@
#ifndef QT_NO_MOVIE
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QMovie;
@@ -108,8 +106,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickAnimatedImage)
-QT_END_HEADER
-
#endif // QT_NO_MOVIE
#endif // QQUICKANIMATEDIMAGE_P_H
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 343cac5d5c..f09e9bb90e 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -365,7 +365,7 @@ QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) :
QQuickItem(parent)
, m_node(0)
, m_material(0)
- , m_sprite(new QQuickSprite)
+ , m_sprite(new QQuickSprite(this))
, m_spriteEngine(0)
, m_curFrame(0)
, m_pleaseReset(false)
@@ -540,7 +540,7 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
m_material = new QQuickAnimatedSpriteMaterial();
- QImage image = m_spriteEngine->assembledImage();
+ QImage image = m_spriteEngine->assembledImage(); //Engine prints errors if there are any
if (image.isNull())
return 0;
m_sheetSize = QSizeF(image.size());
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index 47dd51c3ee..6d0a821a47 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -46,8 +46,6 @@
#include <private/qquicksprite_p.h>
#include <QTime>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QSGContext;
@@ -378,6 +376,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKANIMATEDSPRITE_P_H
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 1cc86bc832..2ba69a383d 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -44,7 +44,6 @@
#include "qquickimagebase_p.h"
-QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QQuickScaleGrid;
@@ -102,6 +101,5 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickBorderImage)
-QT_END_HEADER
#endif // QQUICKBORDERIMAGE_P_H
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 5e1448aab6..c1835d9504 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -51,8 +51,6 @@
#ifndef QT_NO_DRAGANDDROP
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -205,8 +203,6 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QT_NO_DRAGANDDROP
#endif
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
index 14921a2d28..bfc3f922b5 100644
--- a/src/quick/items/qquickdroparea_p.h
+++ b/src/quick/items/qquickdroparea_p.h
@@ -51,8 +51,6 @@
#ifndef QT_NO_DRAGANDDROP
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickDropAreaPrivate;
@@ -162,8 +160,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickDropEvent)
QML_DECLARE_TYPE(QQuickDropArea)
-QT_END_HEADER
-
#endif // QT_NO_DRAGANDDROP
#endif // QQUICKDROPAREA_P_H
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index c1e8dd378c..dd7357822a 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1031,23 +1031,20 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
newY = minY + (newY - minY) / 2;
if (newY < maxY && maxY - minY <= 0)
newY = maxY + (newY - maxY) / 2;
- if (boundsBehavior == QQuickFlickable::StopAtBounds && (newY > minY || newY < maxY)) {
- rejectY = true;
- if (newY < maxY) {
- newY = maxY;
- rejectY = false;
- }
- if (newY > minY) {
- newY = minY;
- rejectY = false;
- }
+ if (boundsBehavior == QQuickFlickable::StopAtBounds && newY <= maxY) {
+ newY = maxY;
+ rejectY = vData.pressPos == maxY && dy < 0;
+ }
+ if (boundsBehavior == QQuickFlickable::StopAtBounds && newY >= minY) {
+ newY = minY;
+ rejectY = vData.pressPos == minY && dy > 0;
}
if (!rejectY && stealMouse && dy != 0.0) {
clearTimeline();
vData.move.setValue(newY);
vMoved = true;
}
- if (overThreshold)
+ if (!rejectY && overThreshold)
stealY = true;
}
}
@@ -1065,24 +1062,22 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
newX = minX + (newX - minX) / 2;
if (newX < maxX && maxX - minX <= 0)
newX = maxX + (newX - maxX) / 2;
- if (boundsBehavior == QQuickFlickable::StopAtBounds && (newX > minX || newX < maxX)) {
- rejectX = true;
- if (newX < maxX) {
- newX = maxX;
- rejectX = false;
- }
- if (newX > minX) {
- newX = minX;
- rejectX = false;
- }
+ if (boundsBehavior == QQuickFlickable::StopAtBounds && newX <= maxX) {
+ newX = maxX;
+ rejectX = hData.pressPos == maxX && dx < 0;
+ }
+ if (boundsBehavior == QQuickFlickable::StopAtBounds && newX >= minX) {
+ newX = minX;
+ rejectX = hData.pressPos == minX && dx > 0;
}
+
if (!rejectX && stealMouse && dx != 0.0) {
clearTimeline();
hData.move.setValue(newX);
hMoved = true;
}
- if (overThreshold)
+ if (!rejectX && overThreshold)
stealX = true;
}
}
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 2e16f11882..5d36ea01ac 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -45,8 +45,6 @@
#include "qquickitem.h"
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickFlickablePrivate;
@@ -278,6 +276,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickFlickable)
-QT_END_HEADER
-
#endif // QQUICKFLICKABLE_P_H
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
index 1bc6f4113d..795dc4f809 100644
--- a/src/quick/items/qquickflipable_p.h
+++ b/src/quick/items/qquickflipable_p.h
@@ -48,8 +48,6 @@
#include <QtGui/qvector3d.h>
#include <QtCore/qobject.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickFlipablePrivate;
@@ -96,6 +94,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickFlipable)
-QT_END_HEADER
-
#endif // QQUICKFLIPABLE_P_H
diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h
index d72eae0805..965c7538bf 100644
--- a/src/quick/items/qquickfocusscope_p.h
+++ b/src/quick/items/qquickfocusscope_p.h
@@ -44,8 +44,6 @@
#include "qquickitem.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QQuickFocusScope : public QQuickItem
@@ -60,6 +58,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickFocusScope)
-QT_END_HEADER
-
#endif // QQUICKFOCUSSCOPE_P_H
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index fd9ce9ffcd..e40d21b498 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -40,10 +40,10 @@
****************************************************************************/
#include "qquickgridview_p.h"
-#include "qquickvisualitemmodel_p.h"
#include "qquickflickable_p_p.h"
#include "qquickitemview_p_p.h"
+#include <private/qqmlobjectmodel_p.h>
#include <private/qquicksmoothedanimation_p_p.h>
#include <QtGui/qevent.h>
@@ -209,7 +209,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems(int fromModelIndex = 0);
- virtual bool applyInsertionChange(const QQuickChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
+ virtual bool applyInsertionChange(const QQmlChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
virtual void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
virtual bool needsRefillForAddedOrRemovedIndex(int index) const;
@@ -463,7 +463,7 @@ void QQuickGridViewPrivate::resetColumns()
{
Q_Q(QQuickGridView);
qreal length = flow == QQuickGridView::FlowLeftToRight ? q->width() : q->height();
- columns = (int)qMax((length + colSize()/2) / colSize(), qreal(1.));
+ columns = qMax(1, qFloor(length / colSize()));
}
FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item)
@@ -2105,13 +2105,16 @@ void QQuickGridView::geometryChanged(const QRectF &newGeometry, const QRectF &ol
QQuickItemView::geometryChanged(newGeometry, oldGeometry);
}
-void QQuickGridView::initItem(int index, QQuickItem *item)
+void QQuickGridView::initItem(int index, QObject *obj)
{
- QQuickItemView::initItem(index, item);
- QQuickGridViewAttached *attached = static_cast<QQuickGridViewAttached *>(
- qmlAttachedPropertiesObject<QQuickGridView>(item));
- if (attached)
- attached->setView(this);
+ QQuickItemView::initItem(index, obj);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(obj);
+ if (item) {
+ QQuickGridViewAttached *attached = static_cast<QQuickGridViewAttached *>(
+ qmlAttachedPropertiesObject<QQuickGridView>(item));
+ if (attached)
+ attached->setView(this);
+ }
}
/*!
@@ -2286,7 +2289,7 @@ void QQuickGridView::moveCurrentIndexRight()
}
}
-bool QQuickGridViewPrivate::applyInsertionChange(const QQuickChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
+bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
{
Q_Q(QQuickGridView);
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
index 64cb814f8c..d98de1050f 100644
--- a/src/quick/items/qquickgridview_p.h
+++ b/src/quick/items/qquickgridview_p.h
@@ -46,11 +46,8 @@
#include <private/qqmlguard_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
-class QQuickVisualModel;
class QQuickGridViewAttached;
class QQuickGridViewPrivate;
class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
@@ -112,7 +109,7 @@ protected:
virtual void viewportMoved(Qt::Orientations);
virtual void keyPressEvent(QKeyEvent *);
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual void initItem(int index, QQuickItem *item);
+ virtual void initItem(int index, QObject *item);
};
class QQuickGridViewAttached : public QQuickItemViewAttached
@@ -145,6 +142,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickGridView)
QML_DECLARE_TYPEINFO(QQuickGridView, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
#endif // QQUICKGRIDVIEW_P_H
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index 9437b47635..b1f27a64ba 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -45,8 +45,6 @@
#include "qquickimagebase_p.h"
#include <QtQuick/qsgtextureprovider.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickImagePrivate;
@@ -114,6 +112,4 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickImage)
-QT_END_HEADER
-
#endif // QQUICKIMAGE_P_H
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index f5ed69129d..388873b4d3 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -45,8 +45,6 @@
#include "qquickimplicitsizeitem_p.h"
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickImageBasePrivate;
@@ -114,6 +112,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKIMAGEBASE_P_H
diff --git a/src/quick/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp
index 3395dafecc..b330b3929f 100644
--- a/src/quick/items/qquickimplicitsizeitem.cpp
+++ b/src/quick/items/qquickimplicitsizeitem.cpp
@@ -53,7 +53,7 @@ void QQuickImplicitSizeItemPrivate::implicitWidthChanged()
change.listener->itemImplicitWidthChanged(q);
}
}
- emit q->implicitWidthChanged();
+ emit q->implicitWidthChanged2();
}
void QQuickImplicitSizeItemPrivate::implicitHeightChanged()
@@ -65,12 +65,14 @@ void QQuickImplicitSizeItemPrivate::implicitHeightChanged()
change.listener->itemImplicitHeightChanged(q);
}
}
- emit q->implicitHeightChanged();
+ emit q->implicitHeightChanged2();
}
QQuickImplicitSizeItem::QQuickImplicitSizeItem(QQuickImplicitSizeItemPrivate &dd, QQuickItem *parent)
: QQuickItem(dd, parent)
{
+ connect(this, SIGNAL(implicitHeightChanged2()), this, SIGNAL(implicitHeightChanged()));
+ connect(this, SIGNAL(implicitWidthChanged2()), this, SIGNAL(implicitWidthChanged()));
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickimplicitsizeitem_p.h b/src/quick/items/qquickimplicitsizeitem_p.h
index 6e306d8375..7557012295 100644
--- a/src/quick/items/qquickimplicitsizeitem_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p.h
@@ -45,23 +45,21 @@
#include "qquickpainteditem.h"
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickImplicitSizeItemPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickImplicitSizeItem : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged)
- Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged)
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged2)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged2)
protected:
QQuickImplicitSizeItem(QQuickImplicitSizeItemPrivate &dd, QQuickItem *parent);
Q_SIGNALS:
- void implicitWidthChanged();
- void implicitHeightChanged();
+ Q_REVISION(1) void implicitWidthChanged2();
+ Q_REVISION(1) void implicitHeightChanged2();
private:
Q_DISABLE_COPY(QQuickImplicitSizeItem)
@@ -70,6 +68,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKIMPLICITSIZEITEM_H
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index d72a7b1a1d..d110a01290 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -78,6 +78,10 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DEBUG
+static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+#endif
+
#ifdef FOCUS_DEBUG
void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1);
void printFocusTree(QQuickItem *item, QQuickItem *scope, int depth)
@@ -739,7 +743,12 @@ void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, co
while (currentItem != initialItem && isNextItem);
}
-const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = {
+struct SigMap {
+ int key;
+ const char *sig;
+};
+
+const SigMap sigMap[] = {
{ Qt::Key_Left, "leftPressed" },
{ Qt::Key_Right, "rightPressed" },
{ Qt::Key_Up, "upPressed" },
@@ -771,6 +780,21 @@ const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = {
{ 0, 0 }
};
+const QByteArray QQuickKeysAttached::keyToSignal(int key)
+{
+ QByteArray keySignal;
+ if (key >= Qt::Key_0 && key <= Qt::Key_9) {
+ keySignal = "digit0Pressed";
+ keySignal[5] = '0' + (key - Qt::Key_0);
+ } else {
+ int i = 0;
+ while (sigMap[i].key && sigMap[i].key != key)
+ ++i;
+ keySignal = sigMap[i].sig;
+ }
+ return keySignal;
+}
+
bool QQuickKeysAttached::isConnected(const char *signalName)
{
Q_D(QQuickKeysAttached);
@@ -1510,6 +1534,11 @@ void QQuickItemPrivate::setAccessibleFlagAndListener()
}
}
+/*!
+Clears all sub focus items from \a scope.
+If \a focus is true, sets the scope's subFocusItem
+to be this item.
+*/
void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
{
Q_Q(QQuickItem);
@@ -1839,6 +1868,11 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
*/
/*!
+ \fn void QQuickItem::activeFocusOnTabChanged(bool)
+ \internal
+*/
+
+/*!
\fn void QQuickItem::childrenChanged()
\internal
*/
@@ -1945,9 +1979,11 @@ static void qt_print_item_count()
QQuickItem::~QQuickItem()
{
#ifndef QT_NO_DEBUG
- --qt_item_count;
- if (qt_item_count < 0)
- qDebug("Item destroyed after qt_print_item_count() was called.");
+ if (qsg_leak_check) {
+ --qt_item_count;
+ if (qt_item_count < 0)
+ qDebug("Item destroyed after qt_print_item_count() was called.");
+ }
#endif
Q_D(QQuickItem);
@@ -1997,6 +2033,93 @@ QQuickItem::~QQuickItem()
}
/*!
+ \internal
+ \brief QQuickItemPrivate::focusNextPrev focuses the next/prev item in the tab-focus-chain
+ \param item The item that currently has the focus
+ \param forward The direction
+ \return Whether the next item in the focus chain is found or not
+
+ If \a next is true, the next item visited will be in depth-first order relative to \a item.
+ If \a next is false, the next item visited will be in reverse depth-first order relative to \a item.
+*/
+bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
+{
+ Q_ASSERT(item);
+ Q_ASSERT(item->activeFocusOnTab());
+
+ QQuickItem *from = 0;
+ if (forward) {
+ from = item->parentItem();
+ } else {
+ if (!item->childItems().isEmpty())
+ from = item->childItems().first();
+ else
+ from = item->parentItem();
+ }
+ bool skip = false;
+ QQuickItem *current = item;
+ do {
+ skip = false;
+ QQuickItem *last = current;
+
+ bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible();
+
+ // coming from parent: check children
+ if (hasChildren && from == current->parentItem()) {
+ if (forward) {
+ current = current->childItems().first();
+ } else {
+ current = current->childItems().last();
+ if (!current->childItems().isEmpty())
+ skip = true;
+ }
+ } else if (hasChildren && forward && from != current->childItems().last()) {
+ // not last child going forwards
+ int nextChild = current->childItems().indexOf(from) + 1;
+ current = current->childItems().at(nextChild);
+ } else if (hasChildren && !forward && from != current->childItems().first()) {
+ // not first child going backwards
+ int prevChild = current->childItems().indexOf(from) - 1;
+ current = current->childItems().at(prevChild);
+ if (!current->childItems().isEmpty())
+ skip = true;
+ // back to the parent
+ } else if (current->parentItem()) {
+ current = current->parentItem();
+ // we would evaluate the parent twice, thus we skip
+ if (forward) {
+ skip = true;
+ } else if (!forward && !current->childItems().isEmpty()) {
+ if (last != current->childItems().first()) {
+ skip = true;
+ } else if (last == current->childItems().first()) {
+ if (current->isFocusScope() && current->activeFocusOnTab() && current->hasActiveFocus())
+ skip = true;
+ }
+ }
+ } else if (hasChildren) {
+ // Wrap around after checking all items forward
+ if (forward) {
+ current = current->childItems().first();
+ } else {
+ current = current->childItems().last();
+ if (!current->childItems().isEmpty())
+ skip = true;
+ }
+ }
+
+ from = last;
+ } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible());
+
+ if (current == item)
+ return false;
+
+ current->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+
+ return true;
+}
+
+/*!
\qmlproperty Item QtQuick2::Item::parent
This property holds the visual parent of the item.
@@ -2057,7 +2180,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
while (!scopeItem->isFocusScope() && scopeItem->parentItem())
scopeItem = scopeItem->parentItem();
if (d->window) {
- QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem,
+ QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
QQuickWindowPrivate::DontChangeFocusProperty);
if (scopeFocusedItem != this)
QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true);
@@ -2120,7 +2243,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
emit scopeFocusedItem->focusChanged(false);
} else {
if (d->window) {
- QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem,
+ QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
QQuickWindowPrivate::DontChangeFocusProperty);
} else {
QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, true);
@@ -2496,6 +2619,7 @@ QQuickItemPrivate::QQuickItemPrivate()
, isAccessible(false)
, culled(false)
, hasCursor(false)
+ , activeFocusOnTab(false)
, dirtyAttributes(0)
, nextDirtyItem(0)
, prevDirtyItem(0)
@@ -2526,11 +2650,13 @@ QQuickItemPrivate::~QQuickItemPrivate()
void QQuickItemPrivate::init(QQuickItem *parent)
{
#ifndef QT_NO_DEBUG
- ++qt_item_count;
- static bool atexit_registered = false;
- if (!atexit_registered) {
- atexit(qt_print_item_count);
- atexit_registered = true;
+ if (qsg_leak_check) {
+ ++qt_item_count;
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_print_item_count);
+ atexit_registered = true;
+ }
}
#endif
@@ -2979,8 +3105,6 @@ QList<QQuickItem *> QQuickItem::childItems() const
If clipping is enabled, an item will clip its own painting, as well
as the painting of its children, to its bounding rectangle.
-
- Non-rectangular clipping regions are not supported for performance reasons.
*/
/*!
\property QQuickItem::clip
@@ -2990,8 +3114,6 @@ QList<QQuickItem *> QQuickItem::childItems() const
as the painting of its children, to its bounding rectangle. If you set
clipping during an item's paint operation, remember to re-set it to
prevent clipping the rest of your scene.
-
- Non-rectangular clipping regions are not supported for performance reasons.
*/
bool QQuickItem::clip() const
{
@@ -3744,29 +3866,44 @@ void QQuickItem::mapToItem(QQmlV8Function *args) const
/*!
\qmlmethod QtQuick2::Item::forceActiveFocus()
+ \overload
Forces active focus on the item.
This method sets focus on the item and ensures that all ancestor
FocusScope objects in the object hierarchy are also given \l focus.
+ The reason for the focus change will be \a Qt::OtherFocusReason. Use
+ the overloaded method to specify the focus reason to enable better
+ handling of the focus change.
+
\sa activeFocus
*/
+void QQuickItem::forceActiveFocus()
+{
+ forceActiveFocus(Qt::OtherFocusReason);
+}
+
/*!
- Forces active focus on the item.
+ \qmlmethod QtQuick2::Item::forceActiveFocus(Qt::FocusReason reason)
+
+ Forces active focus on the item with the given \a reason.
This method sets focus on the item and ensures that all ancestor
FocusScope objects in the object hierarchy are also given \l focus.
- \sa activeFocus
+ \since QtQuick 2.1
+
+ \sa activeFocus, Qt::FocusReason
*/
-void QQuickItem::forceActiveFocus()
+
+void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
{
- setFocus(true);
+ setFocus(true, reason);
QQuickItem *parent = parentItem();
while (parent) {
if (parent->flags() & QQuickItem::ItemIsFocusScope) {
- parent->setFocus(true);
+ parent->setFocus(true, reason);
}
parent = parent->parentItem();
}
@@ -3788,14 +3925,15 @@ void QQuickItem::forceActiveFocus()
*/
QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
{
- // XXX todo - should this include transform etc.?
const QList<QQuickItem *> children = childItems();
for (int i = children.count()-1; i >= 0; --i) {
QQuickItem *child = children.at(i);
- if (child->isVisible() && child->x() <= x
- && child->x() + child->width() >= x
- && child->y() <= y
- && child->y() + child->height() >= y)
+ // Map coordinates to the child element's coordinate space
+ QPointF point = mapToItem(child, QPointF(x, y));
+ if (child->isVisible() && point.x() >= 0
+ && child->width() >= point.x()
+ && point.y() >= 0
+ && child->height() >= point.y())
return child;
}
return 0;
@@ -3954,8 +4092,8 @@ void QQuickItemPrivate::setState(const QString &state)
This property holds the name of the current state of the item.
- If the item is in its default state — that is, no explicit state has been
- set — then this property holds an empty string. Likewise, you can return
+ If the item is in its default state, that is, no explicit state has been
+ set, then this property holds an empty string. Likewise, you can return
an item to its default state by setting this property to an empty string.
\sa {Qt Quick States}
@@ -3965,8 +4103,8 @@ void QQuickItemPrivate::setState(const QString &state)
This property holds the name of the current state of the item.
- If the item is in its default state — that is, no explicit state has been
- set — then this property holds an empty string. Likewise, you can return
+ If the item is in its default state, that is, no explicit state has been
+ set, then this property holds an empty string. Likewise, you can return
an item to its default state by setting this property to an empty string.
\sa {Qt Quick States}
@@ -4130,6 +4268,23 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
else
extra->keyHandler->keyReleased(e, true);
}
+
+ if (e->isAccepted())
+ return;
+
+ //only care about KeyPress now
+ if (q->activeFocusOnTab() && e->type() == QEvent::KeyPress) {
+ bool res = false;
+ if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
+ if (e->key() == Qt::Key_Backtab
+ || (e->key() == Qt::Key_Tab && (e->modifiers() & Qt::ShiftModifier)))
+ res = QQuickItemPrivate::focusNextPrev(q, false);
+ else if (e->key() == Qt::Key_Tab)
+ res = QQuickItemPrivate::focusNextPrev(q, true);
+ if (res)
+ e->setAccepted(true);
+ }
+ }
}
#ifndef QT_NO_IM
@@ -5052,7 +5207,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
q->ungrabMouse();
if (scope && !effectiveEnable && activeFocus) {
windowPriv->clearFocusInScope(
- scope, q, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
+ scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
}
}
@@ -5063,7 +5218,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
if (window && scope && effectiveEnable && focus) {
QQuickWindowPrivate::get(window)->setFocusInScope(
- scope, q, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
+ scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
}
emit q->enabledChanged();
@@ -5292,6 +5447,53 @@ void QQuickItem::setSmooth(bool smooth)
}
/*!
+ \qmlproperty bool QtQuick2::Item::activeFocusOnTab
+
+ This property holds whether the item wants to be in tab focus
+ chain. By default this is set to false.
+
+ The tab focus chain traverses elements by visiting first the
+ parent, and then its children in the order they occur in the
+ children property. Pressing the tab key on an item in the tab
+ focus chain will move keyboard focus to the next item in the
+ chain. Pressing BackTab (normally Shift+Tab) will move focus
+ to the previous item.
+
+ To set up a manual tab focus chain, see \l KeyNavigation. Tab
+ key events used by Keys or KeyNavigation have precedence over
+ focus chain behavior, ignore the events in other key handlers
+ to allow it to propagate.
+*/
+/*!
+ \property QQuickItem::activeFocusOnTab
+
+ This property holds whether the item wants to be in tab focus
+ chain. By default this is set to false.
+*/
+bool QQuickItem::activeFocusOnTab() const
+{
+ Q_D(const QQuickItem);
+ return d->activeFocusOnTab;
+}
+void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
+{
+ Q_D(QQuickItem);
+ if (d->activeFocusOnTab == activeFocusOnTab)
+ return;
+
+ if (window()) {
+ if ((this == window()->activeFocusItem()) && !activeFocusOnTab) {
+ qWarning("QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item.");
+ return;
+ }
+ }
+
+ d->activeFocusOnTab = activeFocusOnTab;
+
+ emit activeFocusOnTabChanged(activeFocusOnTab);
+}
+
+/*!
\qmlproperty bool QtQuick2::Item::antialiasing
Primarily used in Rectangle and image based elements to decide if the item should
@@ -5977,6 +6179,11 @@ bool QQuickItem::hasFocus() const
void QQuickItem::setFocus(bool focus)
{
+ setFocus(focus, Qt::OtherFocusReason);
+}
+
+void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
+{
Q_D(QQuickItem);
if (d->focus == focus)
return;
@@ -5988,9 +6195,9 @@ void QQuickItem::setFocus(bool focus)
scope = scope->parentItem();
if (d->window) {
if (focus)
- QQuickWindowPrivate::get(d->window)->setFocusInScope(scope, this);
+ QQuickWindowPrivate::get(d->window)->setFocusInScope(scope, this, reason);
else
- QQuickWindowPrivate::get(d->window)->clearFocusInScope(scope, this);
+ QQuickWindowPrivate::get(d->window)->clearFocusInScope(scope, this, reason);
} else {
// do the focus changes from setFocusInScope/clearFocusInScope that are
// unrelated to a window
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index b3ac9339a6..c37bc10bdd 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -52,8 +52,6 @@
#include <QtGui/qfont.h>
#include <QtGui/qaccessible.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -134,6 +132,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL)
+ Q_PROPERTY(bool activeFocusOnTab READ activeFocusOnTab WRITE setActiveFocusOnTab NOTIFY activeFocusOnTabChanged FINAL)
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
@@ -263,6 +262,9 @@ public:
bool smooth() const;
void setSmooth(bool);
+ bool activeFocusOnTab() const;
+ void setActiveFocusOnTab(bool);
+
bool antialiasing() const;
void setAntialiasing(bool);
@@ -276,6 +278,7 @@ public:
bool hasActiveFocus() const;
bool hasFocus() const;
void setFocus(bool);
+ void setFocus(bool focus, Qt::FocusReason reason);
bool isFocusScope() const;
QQuickItem *scopedFocusItem() const;
@@ -320,6 +323,7 @@ public:
Q_INVOKABLE void mapFromItem(QQmlV8Function*) const;
Q_INVOKABLE void mapToItem(QQmlV8Function*) const;
Q_INVOKABLE void forceActiveFocus();
+ Q_INVOKABLE void forceActiveFocus(Qt::FocusReason reason);
Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const;
#ifndef QT_NO_IM
@@ -345,6 +349,7 @@ Q_SIGNALS:
void stateChanged(const QString &);
void focusChanged(bool);
void activeFocusChanged(bool);
+ void activeFocusOnTabChanged(bool);
void parentChanged(QQuickItem *);
void transformOriginChanged(TransformOrigin);
void smoothChanged(bool);
@@ -446,6 +451,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickItem)
QML_DECLARE_TYPE(QQuickTransform)
-QT_END_HEADER
-
#endif // QQUICKITEM_H
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index c238477d6f..4bd9d82c20 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -396,8 +396,8 @@ public:
bool antialiasing:1;
bool focus:1;
bool activeFocus:1;
- bool notifiedFocus:1;
// Bit 16
+ bool notifiedFocus:1;
bool notifiedActiveFocus:1;
bool filtersChildMouseEvents:1;
bool explicitVisible:1;
@@ -413,8 +413,8 @@ public:
bool isAccessible:1;
bool culled:1;
bool hasCursor:1;
- // bool dummy:1
// Bit 32
+ bool activeFocusOnTab:1;
enum DirtyType {
TransformOrigin = 0x00000001,
@@ -484,6 +484,8 @@ public:
QTransform itemToWindowTransform() const;
void itemToParentTransform(QTransform &) const;
+ static bool focusNextPrev(QQuickItem *item, bool forward);
+
qreal x;
qreal y;
qreal width;
@@ -819,28 +821,9 @@ private:
virtual void inputMethodEvent(QInputMethodEvent *, bool post);
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
#endif
- const QByteArray keyToSignal(int key) {
- QByteArray keySignal;
- if (key >= Qt::Key_0 && key <= Qt::Key_9) {
- keySignal = "digit0Pressed";
- keySignal[5] = '0' + (key - Qt::Key_0);
- } else {
- int i = 0;
- while (sigMap[i].key && sigMap[i].key != key)
- ++i;
- keySignal = sigMap[i].sig;
- }
- return keySignal;
- }
+ const QByteArray keyToSignal(int key);
bool isConnected(const char *signalName);
-
- struct SigMap {
- int key;
- const char *sig;
- };
-
- static const SigMap sigMap[];
};
Qt::MouseButtons QQuickItemPrivate::acceptedMouseButtons() const
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index 1dfce5233c..796f6c8ade 100644
--- a/src/quick/items/qquickitemanimation_p.h
+++ b/src/quick/items/qquickitemanimation_p.h
@@ -46,8 +46,6 @@
#include <QtQuick/private/qquickanimation_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickParentAnimationPrivate;
@@ -198,6 +196,4 @@ QML_DECLARE_TYPE(QQuickParentAnimation)
QML_DECLARE_TYPE(QQuickAnchorAnimation)
QML_DECLARE_TYPE(QQuickPathAnimation)
-QT_END_HEADER
-
#endif // QQUICKITEMANIMATION_H
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index c04807168f..cd49377822 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -49,6 +49,7 @@
#include "qquicktext_p.h"
#include "qquicktextinput_p.h"
#include "qquicktextedit_p.h"
+#include "qquicktextdocument.h"
#include "qquickimage_p.h"
#include "qquickborderimage_p.h"
#include "qquickscalegrid_p_p.h"
@@ -57,8 +58,6 @@
#include "qquickflickable_p.h"
#include "qquickflickable_p_p.h"
#include "qquicklistview_p.h"
-#include "qquickvisualitemmodel_p.h"
-#include "qquickvisualdatamodel_p.h"
#include "qquickgridview_p.h"
#include "qquickpathview_p.h"
#include "qquickitemviewtransition_p.h"
@@ -159,11 +158,9 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickScale>(uri,major,minor,"Scale");
qmlRegisterType<QQuickText>(uri,major,minor,"Text");
qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
+ qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit");
qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
- qmlRegisterType<QQuickVisualDataModel>(uri,major,minor,"VisualDataModel");
- qmlRegisterType<QQuickVisualDataGroup>(uri,major,minor,"VisualDataGroup");
- qmlRegisterType<QQuickVisualItemModel>(uri,major,minor,"VisualItemModel");
qmlRegisterType<QQuickItemLayer>();
qmlRegisterType<QQuickAnchors>();
@@ -178,12 +175,14 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
#ifndef QT_NO_VALIDATOR
qmlRegisterType<QValidator>();
#endif
- qmlRegisterType<QQuickVisualModel>();
qmlRegisterType<QQuickPen>();
qmlRegisterType<QQuickFlickableVisibleArea>();
qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
QQmlMetaType::setQQuickAnchorLineCompareFunction(compareQQuickAnchorLines);
+ qmlRegisterType<QQuickTextDocument>();
+
+
qmlRegisterUncreatableType<QQuickKeyNavigationAttached>(uri,major,minor,"KeyNavigation",QQuickKeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
qmlRegisterUncreatableType<QQuickKeysAttached>(uri,major,minor,"Keys",QQuickKeysAttached::tr("Keys is only available via attached properties"));
qmlRegisterUncreatableType<QQuickLayoutMirroringAttached>(uri,major,minor,"LayoutMirroring", QQuickLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
@@ -228,6 +227,9 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
#ifndef QT_NO_ACCESSIBILITY
qmlRegisterUncreatableType<QQuickAccessibleAttached>("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties"));
#endif
+
+ qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid");
+ qmlRegisterType<QQuickTextEdit, 1>(uri, 2, 1, "TextEdit");
}
void QQuickItemsModule::defineModule()
diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h
index d21f182cc6..bbc7c5c9e2 100644
--- a/src/quick/items/qquickitemsmodule_p.h
+++ b/src/quick/items/qquickitemsmodule_p.h
@@ -44,8 +44,6 @@
#include <qqml.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItemsModule
@@ -56,7 +54,5 @@ public:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKITEMSMODULE_P_H
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index b73fb8c5b6..72f892178f 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -41,6 +41,7 @@
#include "qquickitemview_p_p.h"
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQml/QQmlInfo>
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
@@ -147,14 +148,14 @@ bool QQuickItemViewChangeSet::hasPendingChanges() const
return !pendingChanges.isEmpty();
}
-void QQuickItemViewChangeSet::applyChanges(const QQuickChangeSet &changeSet)
+void QQuickItemViewChangeSet::applyChanges(const QQmlChangeSet &changeSet)
{
pendingChanges.apply(changeSet);
int moveId = -1;
int moveOffset = 0;
- foreach (const QQuickChangeSet::Remove &r, changeSet.removes()) {
+ foreach (const QQmlChangeSet::Remove &r, changeSet.removes()) {
itemCount -= r.count;
if (moveId == -1 && newCurrentIndex >= r.index + r.count) {
newCurrentIndex -= r.count;
@@ -173,7 +174,7 @@ void QQuickItemViewChangeSet::applyChanges(const QQuickChangeSet &changeSet)
currentChanged = true;
}
}
- foreach (const QQuickChangeSet::Insert &i, changeSet.inserts()) {
+ foreach (const QQmlChangeSet::Insert &i, changeSet.inserts()) {
if (moveId == -1) {
if (itemCount && newCurrentIndex >= i.index) {
newCurrentIndex += i.count;
@@ -248,10 +249,8 @@ QQuickItemView::~QQuickItemView()
QQuickItem *QQuickItemView::currentItem() const
{
Q_D(const QQuickItemView);
- if (!d->currentItem)
- return 0;
const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
- return d->currentItem->item;
+ return d->currentItem ? d->currentItem->item : 0;
}
QVariant QQuickItemView::model() const
@@ -266,14 +265,14 @@ void QQuickItemView::setModel(const QVariant &model)
if (d->modelVariant == model)
return;
if (d->model) {
- disconnect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
- disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
- disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- disconnect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
+ disconnect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+ disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
}
- QQuickVisualModel *oldModel = d->model;
+ QQmlInstanceModel *oldModel = d->model;
d->clear();
d->model = 0;
@@ -281,8 +280,8 @@ void QQuickItemView::setModel(const QVariant &model)
d->modelVariant = model;
QObject *object = qvariant_cast<QObject*>(model);
- QQuickVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
+ QQmlInstanceModel *vim = 0;
+ if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
if (d->ownModel) {
delete oldModel;
d->ownModel = false;
@@ -290,22 +289,22 @@ void QQuickItemView::setModel(const QVariant &model)
d->model = vim;
} else {
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this), this);
+ d->model = new QQmlDelegateModel(qmlContext(this), this);
d->ownModel = true;
if (isComponentComplete())
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
} else {
d->model = oldModel;
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
dataModel->setModel(model);
}
if (d->model) {
d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
- connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
- connect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
+ connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
+ connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+ connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
if (isComponentComplete()) {
d->updateSectionCriteria();
d->refill();
@@ -319,8 +318,8 @@ void QQuickItemView::setModel(const QVariant &model)
}
}
- connect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
+ connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(modelUpdated(QQmlChangeSet,bool)));
emit countChanged();
}
emit modelChanged();
@@ -330,7 +329,7 @@ QQmlComponent *QQuickItemView::delegate() const
{
Q_D(const QQuickItemView);
if (d->model) {
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
return dataModel->delegate();
}
@@ -343,10 +342,10 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate)
if (delegate == this->delegate())
return;
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
int oldCount = dataModel->count();
dataModel->setDelegate(delegate);
if (isComponentComplete()) {
@@ -371,6 +370,7 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate)
emit countChanged();
}
emit delegateChanged();
+ d->delegateValidated = false;
}
@@ -972,7 +972,7 @@ void QQuickItemViewPrivate::applyPendingChanges()
layout();
}
-int QQuickItemViewPrivate::findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector<QQuickChangeSet::Remove> &changes) const
+int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Remove> &changes) const
{
for (int i=0; i<changes.count(); i++) {
for (int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
@@ -1152,7 +1152,7 @@ void QQuickItemView::destroyRemoved()
d->forceLayoutPolish();
}
-void QQuickItemView::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
+void QQuickItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickItemView);
if (reset) {
@@ -1388,7 +1388,7 @@ void QQuickItemView::componentComplete()
{
Q_D(QQuickItemView);
if (d->model && d->ownModel)
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
QQuickFlickable::componentComplete();
@@ -1440,7 +1440,7 @@ QQuickItemViewPrivate::QQuickItemViewPrivate()
, inLayout(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, fillCacheBuffer(false), inRequest(false)
- , runDelayedRemoveTransition(false)
+ , runDelayedRemoveTransition(false), delegateValidated(false)
{
bufferPause.addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
bufferPause.setLoopCount(1);
@@ -1874,8 +1874,8 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
totalInsertionResult->visiblePos = prevViewPos;
totalRemovalResult->visiblePos = prevViewPos;
- const QVector<QQuickChangeSet::Remove> &removals = currentChanges.pendingChanges.removes();
- const QVector<QQuickChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts();
+ const QVector<QQmlChangeSet::Remove> &removals = currentChanges.pendingChanges.removes();
+ const QVector<QQmlChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts();
ChangeResult insertionResult(prevViewPos);
ChangeResult removalResult(prevViewPos);
@@ -1895,7 +1895,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
}
}
if (runDelayedRemoveTransition) {
- QQuickChangeSet::Remove removal;
+ QQmlChangeSet::Remove removal;
for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
FxViewItem *item = *it;
if (item->index == -1 && !item->attached->delayRemove()) {
@@ -1963,7 +1963,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// Whatever removed/moved items remain are no longer visible items.
prepareRemoveTransitions(&currentChanges.removedItems);
- for (QHash<QQuickChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
+ for (QHash<QQmlChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
it != currentChanges.removedItems.end(); ++it) {
releaseItem(it.value());
}
@@ -1992,7 +1992,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
return visibleAffected;
}
-bool QQuickItemViewPrivate::applyRemovalChange(const QQuickChangeSet::Remove &removal, ChangeResult *removeResult, int *removedCount)
+bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Remove &removal, ChangeResult *removeResult, int *removedCount)
{
Q_Q(QQuickItemView);
bool visibleAffected = false;
@@ -2042,7 +2042,7 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQuickChangeSet::Remove &re
return visibleAffected;
}
-void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QQuickChangeSet::Remove &removal, ChangeResult *removeResult)
+void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QQmlChangeSet::Remove &removal, ChangeResult *removeResult)
{
if (removeResult->visiblePos.isValid()) {
if (item->position() < removeResult->visiblePos)
@@ -2055,7 +2055,7 @@ void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QQuickChangeSet::
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true);
} else {
// track item so it is released later
- currentChanges.removedItems.insertMulti(QQuickChangeSet::MoveKey(), item);
+ currentChanges.removedItems.insertMulti(QQmlChangeSet::MoveKey(), item);
}
if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
removeResult->changedFirstItem = true;
@@ -2115,19 +2115,19 @@ void QQuickItemViewPrivate::prepareVisibleItemTransitions()
return;
// must call for every visible item to init or discard transitions
- QRectF viewBounds(0, position(), q->width(), q->height());
+ QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
for (int i=0; i<visibleItems.count(); i++)
visibleItems[i]->prepareTransition(transitioner, viewBounds);
}
-void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QQuickChangeSet::MoveKey, FxViewItem *> *removedItems)
+void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
{
if (!transitioner)
return;
if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)
|| transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
- for (QHash<QQuickChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
+ for (QHash<QQmlChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
it != removedItems->end(); ) {
bool isRemove = it.key().moveId < 0;
if (isRemove) {
@@ -2197,7 +2197,20 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
requestedIndex = modelIndex;
inRequest = true;
- if (QQuickItem *item = model->item(modelIndex, asynchronous)) {
+ QObject* object = model->object(modelIndex, asynchronous);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (!item) {
+ if (object) {
+ model->release(object);
+ if (!delegateValidated) {
+ delegateValidated = true;
+ QObject* delegate = q->delegate();
+ qmlInfo(delegate ? delegate : q) << q->tr("Delegate must be of Item type");
+ }
+ }
+ inRequest = false;
+ return 0;
+ } else {
item->setParentItem(q->contentItem());
if (requestedIndex == modelIndex)
requestedIndex = -1;
@@ -2212,15 +2225,13 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
inRequest = false;
return viewItem;
}
-
- inRequest = false;
- return 0;
}
-void QQuickItemView::createdItem(int index, QQuickItem *item)
+void QQuickItemView::createdItem(int index, QObject* object)
{
Q_D(QQuickItemView);
+ QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
if (!d->inRequest) {
d->unrequestedItems.insert(item, index);
d->requestedIndex = -1;
@@ -2235,16 +2246,21 @@ void QQuickItemView::createdItem(int index, QQuickItem *item)
}
}
-void QQuickItemView::initItem(int, QQuickItem *item)
+void QQuickItemView::initItem(int, QObject *object)
{
- item->setZ(1);
- item->setParentItem(contentItem());
- QQuickItemPrivate::get(item)->setCulled(true);
+ QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
+ if (item) {
+ item->setZ(1);
+ item->setParentItem(contentItem());
+ QQuickItemPrivate::get(item)->setCulled(true);
+ }
}
-void QQuickItemView::destroyingItem(QQuickItem *item)
+void QQuickItemView::destroyingItem(QObject *object)
{
Q_D(QQuickItemView);
+ QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
+ item->setParentItem(0);
d->unrequestedItems.remove(item);
}
@@ -2257,14 +2273,16 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item)
trackedItem = 0;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item->item);
itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
- QQuickVisualModel::ReleaseFlags flags = model->release(item->item);
+ QQmlInstanceModel::ReleaseFlags flags = model->release(item->item);
if (flags == 0) {
// item was not destroyed, and we no longer reference it.
QQuickItemPrivate::get(item->item)->setCulled(true);
unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ } else if (flags & QQmlInstanceModel::Destroyed) {
+ item->item->setParentItem(0);
}
delete item;
- return flags != QQuickVisualModel::Referenced;
+ return flags != QQmlInstanceModel::Referenced;
}
QQuickItem *QQuickItemViewPrivate::createHighlightItem()
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 82180a2e13..b0f910680a 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -44,11 +44,9 @@
#include "qquickflickable_p.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
-class QQuickChangeSet;
+class QQmlChangeSet;
class QQuickItemViewPrivate;
@@ -257,10 +255,10 @@ protected:
protected slots:
void destroyRemoved();
- void createdItem(int index, QQuickItem *item);
- virtual void initItem(int index, QQuickItem *item);
- void modelUpdated(const QQuickChangeSet &changeSet, bool reset);
- void destroyingItem(QQuickItem *item);
+ void createdItem(int index, QObject *item);
+ virtual void initItem(int index, QObject *item);
+ void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
+ void destroyingItem(QObject *item);
void animStopped();
void trackedPositionChanged();
@@ -352,7 +350,5 @@ public:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKITEMVIEW_P_H
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index 0efc458c3d..1fa933ebd1 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -45,13 +45,11 @@
#include "qquickitemview_p.h"
#include "qquickitemviewtransition_p.h"
#include "qquickflickable_p_p.h"
-#include "qquickvisualdatamodel_p.h"
-#include "qquickvisualitemmodel_p.h"
-#include <private/qquickchangeset_p.h>
+#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <QtQml/private/qqmlchangeset_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -103,14 +101,14 @@ public:
void prepare(int currentIndex, int count);
void reset();
- void applyChanges(const QQuickChangeSet &changeSet);
+ void applyChanges(const QQmlChangeSet &changeSet);
void applyBufferedChanges(const QQuickItemViewChangeSet &other);
int itemCount;
int newCurrentIndex;
- QQuickChangeSet pendingChanges;
- QHash<QQuickChangeSet::MoveKey, FxViewItem *> removedItems;
+ QQmlChangeSet pendingChanges;
+ QHash<QQmlChangeSet::MoveKey, FxViewItem *> removedItems;
bool active : 1;
bool currentChanged : 1;
@@ -209,18 +207,18 @@ public:
void applyPendingChanges();
bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
- bool applyRemovalChange(const QQuickChangeSet::Remove &removal, ChangeResult *changeResult, int *removedCount);
- void removeItem(FxViewItem *item, const QQuickChangeSet::Remove &removal, ChangeResult *removeResult);
+ bool applyRemovalChange(const QQmlChangeSet::Remove &removal, ChangeResult *changeResult, int *removedCount);
+ void removeItem(FxViewItem *item, const QQmlChangeSet::Remove &removal, ChangeResult *removeResult);
void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
void createTransitioner();
void prepareVisibleItemTransitions();
- void prepareRemoveTransitions(QHash<QQuickChangeSet::MoveKey, FxViewItem *> *removedItems);
+ void prepareRemoveTransitions(QHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems);
bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
virtual void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item);
- int findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector<QQuickChangeSet::Remove> &changes) const;
+ int findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Remove> &changes) const;
void checkVisible() const;
void showVisibleItems() const;
@@ -251,7 +249,7 @@ public:
q->polish();
}
- QQmlGuard<QQuickVisualModel> model;
+ QQmlGuard<QQmlInstanceModel> model;
QVariant modelVariant;
int itemCount;
int buffer;
@@ -286,8 +284,8 @@ public:
struct MovedItem {
FxViewItem *item;
- QQuickChangeSet::MoveKey moveKey;
- MovedItem(FxViewItem *i, QQuickChangeSet::MoveKey k)
+ QQmlChangeSet::MoveKey moveKey;
+ MovedItem(FxViewItem *i, QQmlChangeSet::MoveKey k)
: item(i), moveKey(k) {}
};
QQuickItemViewTransitioner *transitioner;
@@ -309,6 +307,7 @@ public:
bool fillCacheBuffer : 1;
bool inRequest : 1;
bool runDelayedRemoveTransition : 1;
+ bool delegateValidated : 1;
protected:
virtual Qt::Orientation layoutOrientation() const = 0;
@@ -346,7 +345,7 @@ protected:
virtual void layoutVisibleItems(int fromModelIndex = 0) = 0;
virtual void changedVisibleIndex(int newIndex) = 0;
- virtual bool applyInsertionChange(const QQuickChangeSet::Insert &insert, ChangeResult *changeResult,
+ virtual bool applyInsertionChange(const QQmlChangeSet::Insert &insert, ChangeResult *changeResult,
QList<FxViewItem *> *newItems, QList<MovedItem> *movingIntoView) = 0;
virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; }
@@ -363,6 +362,4 @@ protected:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKITEMVIEW_P_P_H
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
index 2667971fd7..4fb4386c57 100644
--- a/src/quick/items/qquickitemviewtransition_p.h
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -44,8 +44,6 @@
#include <private/qquicktransitionmanager_p_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -211,6 +209,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickViewTransitionAttached)
QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
#endif // QQUICKITEMVIEWTRANSITION_P_P_H
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 57f1b99456..53dc715469 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -41,8 +41,8 @@
#include "qquicklistview_p.h"
#include "qquickitemview_p_p.h"
-#include "qquickvisualitemmodel_p.h"
+#include <private/qqmlobjectmodel_p.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlinfo.h>
@@ -106,7 +106,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems(int fromModelIndex = 0);
- virtual bool applyInsertionChange(const QQuickChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
+ virtual bool applyInsertionChange(const QQmlChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
virtual void updateSectionCriteria();
@@ -172,7 +172,9 @@ public:
, highlightMoveVelocity(400), highlightResizeVelocity(400), highlightResizeDuration(-1)
, sectionCriteria(0), currentSectionItem(0), nextSectionItem(0)
, overshootDist(0.0), correctFlick(false), inFlickCorrection(false)
- {}
+ {
+ highlightMoveDuration = -1; //override default value set in base class
+ }
~QQuickListViewPrivate() {
delete highlightPosAnimator;
delete highlightSizeAnimator;
@@ -2803,13 +2805,16 @@ void QQuickListView::geometryChanged(const QRectF &newGeometry, const QRectF &ol
QQuickItemView::geometryChanged(newGeometry, oldGeometry);
}
-void QQuickListView::initItem(int index, QQuickItem *item)
+void QQuickListView::initItem(int index, QObject *object)
{
- QQuickItemView::initItem(index, item);
- QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
- qmlAttachedPropertiesObject<QQuickListView>(item));
- if (attached)
- attached->setView(this);
+ QQuickItemView::initItem(index, object);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (item) {
+ QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
+ qmlAttachedPropertiesObject<QQuickListView>(item));
+ if (attached)
+ attached->setView(this);
+ }
}
@@ -2867,7 +2872,7 @@ void QQuickListViewPrivate::updateSectionCriteria()
}
}
-bool QQuickListViewPrivate::applyInsertionChange(const QQuickChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
+bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
{
int modelIndex = change.index;
int count = change.count;
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
index f6c405e86b..3e766f8068 100644
--- a/src/quick/items/qquicklistview_p.h
+++ b/src/quick/items/qquicklistview_p.h
@@ -46,8 +46,6 @@
#include <private/qqmlguard_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickListView;
@@ -96,7 +94,7 @@ private:
};
-class QQuickVisualModel;
+class QQmlInstanceModel;
class QQuickListViewAttached;
class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView
{
@@ -169,7 +167,7 @@ protected:
virtual void viewportMoved(Qt::Orientations orient);
virtual void keyPressEvent(QKeyEvent *);
virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
- virtual void initItem(int index, QQuickItem *item);
+ virtual void initItem(int index, QObject *item);
};
class QQuickListViewAttached : public QQuickItemViewAttached
@@ -205,6 +203,4 @@ QML_DECLARE_TYPEINFO(QQuickListView, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickListView)
QML_DECLARE_TYPE(QQuickViewSection)
-QT_END_HEADER
-
#endif // QQUICKLISTVIEW_P_H
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 61f9a27d3b..0d14f3e266 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -335,41 +335,42 @@ bool QQuickLoader::active() const
void QQuickLoader::setActive(bool newVal)
{
Q_D(QQuickLoader);
- if (d->active != newVal) {
- d->active = newVal;
- if (newVal == true) {
- if (d->loadingFromSource) {
- loadFromSource();
- } else {
- loadFromSourceComponent();
- }
+ if (d->active == newVal)
+ return;
+
+ d->active = newVal;
+ if (newVal == true) {
+ if (d->loadingFromSource) {
+ loadFromSource();
} else {
- // cancel any current incubation
- if (d->incubator) {
- d->incubator->clear();
- delete d->itemContext;
- d->itemContext = 0;
- }
+ loadFromSourceComponent();
+ }
+ } else {
+ // cancel any current incubation
+ if (d->incubator) {
+ d->incubator->clear();
+ delete d->itemContext;
+ d->itemContext = 0;
+ }
- if (d->item) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->removeItemChangeListener(d, watchedChanges);
+ if (d->item) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
+ p->removeItemChangeListener(d, watchedChanges);
- // We can't delete immediately because our item may have triggered
- // the Loader to load a different item.
- d->item->setParentItem(0);
- d->item->setVisible(false);
- d->item = 0;
- }
- if (d->object) {
- d->object->deleteLater();
- d->object = 0;
- emit itemChanged();
- }
- emit statusChanged();
+ // We can't delete immediately because our item may have triggered
+ // the Loader to load a different item.
+ d->item->setParentItem(0);
+ d->item->setVisible(false);
+ d->item = 0;
}
- emit activeChanged();
+ if (d->object) {
+ d->object->deleteLater();
+ d->object = 0;
+ emit itemChanged();
+ }
+ emit statusChanged();
}
+ emit activeChanged();
}
@@ -886,16 +887,19 @@ void QQuickLoader::setAsynchronous(bool a)
void QQuickLoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
{
Q_Q(QQuickLoader);
- if (!item || updatingSize)
+ if (!item)
return;
- updatingSize = true;
-
if (loaderGeometryChanged && q->widthValid())
item->setWidth(q->width());
if (loaderGeometryChanged && q->heightValid())
item->setHeight(q->height());
+ if (updatingSize)
+ return;
+
+ updatingSize = true;
+
q->setImplicitSize(getImplicitWidth(), getImplicitHeight());
updatingSize = false;
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index ebf9e16c1e..6a69ccd32f 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -44,8 +44,6 @@
#include "qquickimplicitsizeitem_p.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickLoaderPrivate;
@@ -115,6 +113,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickLoader)
-QT_END_HEADER
-
#endif // QQUICKLOADER_P_H
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index e75a60181f..ad0a265035 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -797,9 +797,6 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
curLocalPos = event->windowPos();
}
- qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
- qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
-
if (keepMouseGrab() && d->stealMouse && !d->drag->active())
d->drag->setActive(true);
@@ -807,38 +804,31 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
: d->targetStartPos;
- QPointF dragPos = d->drag->target()->position();
-
bool dragX = drag()->axis() & QQuickDrag::XAxis;
bool dragY = drag()->axis() & QQuickDrag::YAxis;
- if (dragX && d->drag->active()) {
- qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x();
- if (x < drag()->xmin())
- x = drag()->xmin();
- else if (x > drag()->xmax())
- x = drag()->xmax();
- dragPos.setX(x);
+ QPointF dragPos = d->drag->target()->position();
+ if (dragX) {
+ dragPos.setX(qBound(
+ d->drag->xmin(),
+ startPos.x() + curLocalPos.x() - startLocalPos.x(),
+ d->drag->xmax()));
}
- if (dragY && d->drag->active()) {
- qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y();
- if (y < drag()->ymin())
- y = drag()->ymin();
- else if (y > drag()->ymax())
- y = drag()->ymax();
- dragPos.setY(y);
+ if (dragY) {
+ dragPos.setY(qBound(
+ d->drag->ymin(),
+ startPos.y() + curLocalPos.y() - startLocalPos.y(),
+ d->drag->ymax()));
}
- d->drag->target()->setPosition(dragPos);
-
- if (!keepMouseGrab()) {
- bool xDragged = QQuickWindowPrivate::dragOverThreshold(dx, Qt::XAxis, event);
- bool yDragged = QQuickWindowPrivate::dragOverThreshold(dy, Qt::YAxis, event);
- if ((!dragY && !yDragged && dragX && xDragged)
- || (!dragX && !xDragged && dragY && yDragged)
- || (dragX && dragY && (xDragged || yDragged))) {
- setKeepMouseGrab(true);
- d->stealMouse = true;
- }
+ if (d->drag->active())
+ d->drag->target()->setPosition(dragPos);
+
+ if (!keepMouseGrab()
+ && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event)
+ || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event))) {
+ setKeepMouseGrab(true);
+ d->stealMouse = true;
+ d->startScene = event->windowPos();
}
d->moved = true;
diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h
index eb49535d95..ad15167b10 100644
--- a/src/quick/items/qquickmousearea_p.h
+++ b/src/quick/items/qquickmousearea_p.h
@@ -46,8 +46,6 @@
#include <private/qtquickglobal_p.h>
#include <QtCore/qstringlist.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickMouseEvent;
@@ -252,6 +250,4 @@ QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
#endif
QML_DECLARE_TYPE(QQuickMouseArea)
-QT_END_HEADER
-
#endif // QQUICKMOUSEAREA_P_H
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 1ab934e06d..e2ae5ed24e 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -50,8 +50,6 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qstylehints.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickMultiPointTouchArea;
@@ -271,6 +269,4 @@ QML_DECLARE_TYPE(QQuickTouchPoint)
QML_DECLARE_TYPE(QQuickGrabGestureEvent)
QML_DECLARE_TYPE(QQuickMultiPointTouchArea)
-QT_END_HEADER
-
#endif // QQUICKMULTIPOINTTOUCHAREA_H
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index d2d7a54467..88924003b8 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -45,8 +45,6 @@
#include <QtQuick/qquickitem.h>
#include <QtGui/qcolor.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickPaintedItemPrivate;
@@ -125,6 +123,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPaintedItem::PerformanceHints)
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKPAINTEDITEM_P_H
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index a7be50bc11..e9aa6985fc 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -46,8 +46,9 @@
#include <QtQuick/private/qquickstate_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlopenmetaobject_p.h>
-#include <private/qquickchangeset_p.h>
+#include <private/qqmlchangeset_p.h>
+#include <QtQml/qqmlinfo.h>
#include <QtGui/qevent.h>
#include <QtGui/qevent.h>
#include <QtGui/qguiapplication.h>
@@ -117,7 +118,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate()
, offset(0.0), offsetAdj(0.0), mappedRange(1.0), mappedCache(0.0)
, stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true)
, autoHighlight(true), highlightUp(false), layoutScheduled(false)
- , moving(false), flicking(false), dragging(false), inRequest(false)
+ , moving(false), flicking(false), dragging(false), inRequest(false), delegateValidated(false)
, dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY)
, moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0)
, firstIndex(-1), pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
@@ -150,8 +151,18 @@ QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool async)
requestedIndex = modelIndex;
requestedZ = z;
inRequest = true;
- QQuickItem *item = model->item(modelIndex, async);
- if (item) {
+ QObject *object = model->object(modelIndex, async);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (!item) {
+ if (object) {
+ model->release(object);
+ if (!delegateValidated) {
+ delegateValidated = true;
+ QObject* delegate = q->delegate();
+ qmlInfo(delegate ? delegate : q) << q->tr("Delegate must be of Item type");
+ }
+ }
+ } else {
item->setParentItem(q);
requestedIndex = -1;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -161,9 +172,10 @@ QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool async)
return item;
}
-void QQuickPathView::createdItem(int index, QQuickItem *item)
+void QQuickPathView::createdItem(int index, QObject *object)
{
Q_D(QQuickPathView);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (d->requestedIndex != index) {
qPathViewAttachedType = d->attachedType();
QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
@@ -181,10 +193,11 @@ void QQuickPathView::createdItem(int index, QQuickItem *item)
}
}
-void QQuickPathView::initItem(int index, QQuickItem *item)
+void QQuickPathView::initItem(int index, QObject *object)
{
Q_D(QQuickPathView);
- if (d->requestedIndex == index) {
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (item && d->requestedIndex == index) {
QQuickItemPrivate::get(item)->setCulled(true);
item->setParentItem(this);
qPathViewAttachedType = d->attachedType();
@@ -209,10 +222,14 @@ void QQuickPathViewPrivate::releaseItem(QQuickItem *item)
return;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
- if (model->release(item) == 0) {
+ QQmlInstanceModel::ReleaseFlags flags = model->release(item);
+ if (!flags) {
// item was not destroyed, and we no longer reference it.
if (QQuickPathViewAttached *att = attached(item))
att->setOnPath(false);
+ } else if (flags & QQmlInstanceModel::Destroyed) {
+ // but we still reference it
+ item->setParentItem(0);
}
}
@@ -619,19 +636,19 @@ void QQuickPathView::setModel(const QVariant &model)
return;
if (d->model) {
- qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, QQuickPathView, SLOT(modelUpdated(QQuickChangeSet,bool)));
- qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(createdItem(int,QQuickItem*)),
- this, QQuickPathView, SLOT(createdItem(int,QQuickItem*)));
- qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(initItem(int,QQuickItem*)),
- this, QQuickPathView, SLOT(initItem(int,QQuickItem*)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, QQuickPathView, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(createdItem(int,QObject*)),
+ this, QQuickPathView, SLOT(createdItem(int,QObject*)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(initItem(int,QObject*)),
+ this, QQuickPathView, SLOT(initItem(int,QObject*)));
d->clear();
}
d->modelVariant = model;
QObject *object = qvariant_cast<QObject*>(model);
- QQuickVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
+ QQmlInstanceModel *vim = 0;
+ if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
if (d->ownModel) {
delete d->model;
d->ownModel = false;
@@ -639,23 +656,23 @@ void QQuickPathView::setModel(const QVariant &model)
d->model = vim;
} else {
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
if (isComponentComplete())
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
dataModel->setModel(model);
}
int oldModelCount = d->modelCount;
d->modelCount = 0;
if (d->model) {
- qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, QQuickPathView, SLOT(modelUpdated(QQuickChangeSet,bool)));
- qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(createdItem(int,QQuickItem*)),
- this, QQuickPathView, SLOT(createdItem(int,QQuickItem*)));
- qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(initItem(int,QQuickItem*)),
- this, QQuickPathView, SLOT(initItem(int,QQuickItem*)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, QQuickPathView, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(createdItem(int,QObject*)),
+ this, QQuickPathView, SLOT(createdItem(int,QObject*)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(initItem(int,QObject*)),
+ this, QQuickPathView, SLOT(initItem(int,QObject*)));
d->modelCount = d->model->count();
}
if (isComponentComplete()) {
@@ -1210,7 +1227,7 @@ QQmlComponent *QQuickPathView::delegate() const
{
Q_D(const QQuickPathView);
if (d->model) {
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
return dataModel->delegate();
}
@@ -1223,10 +1240,10 @@ void QQuickPathView::setDelegate(QQmlComponent *delegate)
if (delegate == this->delegate())
return;
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
int oldCount = dataModel->count();
dataModel->setDelegate(delegate);
d->modelCount = dataModel->count();
@@ -1234,6 +1251,7 @@ void QQuickPathView::setDelegate(QQmlComponent *delegate)
if (oldCount != dataModel->count())
emit countChanged();
emit delegateChanged();
+ d->delegateValidated = false;
}
}
@@ -1821,7 +1839,7 @@ void QQuickPathView::componentComplete()
{
Q_D(QQuickPathView);
if (d->model && d->ownModel)
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
QQuickItem::componentComplete();
@@ -1983,7 +2001,7 @@ void QQuickPathView::refill()
d->releaseItem(d->itemCache.takeLast());
}
-void QQuickPathView::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
+void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickPathView);
if (!d->model || !d->model->isValid() || !d->path || !isComponentComplete())
@@ -2004,7 +2022,7 @@ void QQuickPathView::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
int moveOffset;
bool currentChanged = false;
bool changedOffset = false;
- foreach (const QQuickChangeSet::Remove &r, changeSet.removes()) {
+ foreach (const QQmlChangeSet::Remove &r, changeSet.removes()) {
if (moveId == -1 && d->currentIndex >= r.index + r.count) {
d->currentIndex -= r.count;
currentChanged = true;
@@ -2030,7 +2048,7 @@ void QQuickPathView::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
}
d->modelCount -= r.count;
}
- foreach (const QQuickChangeSet::Insert &i, changeSet.inserts()) {
+ foreach (const QQmlChangeSet::Insert &i, changeSet.inserts()) {
if (d->modelCount) {
if (moveId == -1 && i.index <= d->currentIndex) {
d->currentIndex += i.count;
@@ -2082,7 +2100,7 @@ void QQuickPathView::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
emit countChanged();
}
-void QQuickPathView::destroyingItem(QQuickItem *item)
+void QQuickPathView::destroyingItem(QObject *item)
{
Q_UNUSED(item);
}
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 9cb6b881a0..998707aa41 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -46,11 +46,9 @@
#include <private/qquickpath_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
-class QQuickChangeSet;
+class QQmlChangeSet;
class QQuickPathViewPrivate;
class QQuickPathViewAttached;
@@ -216,10 +214,10 @@ private Q_SLOTS:
void refill();
void ticked();
void movementEnding();
- void modelUpdated(const QQuickChangeSet &changeSet, bool reset);
- void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
- void destroyingItem(QQuickItem *item);
+ void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
+ void createdItem(int index, QObject *item);
+ void initItem(int index, QObject *item);
+ void destroyingItem(QObject *item);
void pathUpdated();
private:
@@ -281,6 +279,5 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickPathView)
QML_DECLARE_TYPEINFO(QQuickPathView, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
#endif // QQUICKPATHVIEW_P_H
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index 9f504db22f..26533057d1 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -55,7 +55,6 @@
#include "qquickpathview_p.h"
#include "qquickitem_p.h"
-#include "qquickvisualdatamodel_p.h"
#include <QtQml/qqml.h>
#include <QtCore/qdatetime.h>
@@ -63,6 +62,7 @@
#include <private/qquickanimation_p_p.h>
#include <private/qqmlguard_p.h>
+#include <private/qqmldelegatemodel_p.h>
#include <private/qquicktimeline_p_p.h>
QT_BEGIN_NAMESPACE
@@ -152,6 +152,7 @@ public:
bool dragging : 1;
bool requestedOnPath : 1;
bool inRequest : 1;
+ bool delegateValidated : 1;
QElapsedTimer timer;
qint64 lastPosTime;
QPointF lastPos;
@@ -168,7 +169,7 @@ public:
qreal requestedZ;
QList<QQuickItem *> items;
QList<QQuickItem *> itemCache;
- QQmlGuard<QQuickVisualModel> model;
+ QQmlGuard<QQmlInstanceModel> model;
QVariant modelVariant;
enum MovementReason { Other, SetIndex, Mouse };
MovementReason moveReason;
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index 2f22b4e4a7..4fc77d7f9c 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -44,8 +44,6 @@
#include "qquickitem.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
@@ -301,7 +299,5 @@ QML_DECLARE_TYPE(QQuickPinch)
QML_DECLARE_TYPE(QQuickPinchEvent)
QML_DECLARE_TYPE(QQuickPinchArea)
-QT_END_HEADER
-
#endif // QQUICKPINCHAREA_H
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 2b03ed2dc4..4a74c0bfba 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -1102,6 +1102,8 @@ QQuickGrid::QQuickGrid(QQuickItem *parent)
, m_useRowSpacing(false)
, m_useColumnSpacing(false)
, m_flow(LeftToRight)
+ , m_hItemAlign(AlignLeft)
+ , m_vItemAlign(AlignTop)
{
}
@@ -1178,7 +1180,7 @@ void QQuickGrid::setFlow(Flow flow)
By default this property is not set.
\sa columnSpacing
- \since QtQuick2.0
+ \since QtQuick 2.0
*/
void QQuickGrid::setRowSpacing(const qreal rowSpacing)
{
@@ -1200,7 +1202,7 @@ void QQuickGrid::setRowSpacing(const qreal rowSpacing)
By default this property is not set.
\sa rowSpacing
- \since QtQuick2.0
+ \since QtQuick 2.0
*/
void QQuickGrid::setColumnSpacing(const qreal columnSpacing)
{
@@ -1248,6 +1250,7 @@ void QQuickGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
prePositioning();
emit layoutDirectionChanged();
emit effectiveLayoutDirectionChanged();
+ emit effectiveHorizontalAlignmentChanged(effectiveHAlign());
}
}
@@ -1266,6 +1269,97 @@ Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const
return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::horizontalItmeAlignment
+ \qmlproperty enumeration QtQuick2::Grid::verticalItemAlignment
+ \qmlproperty enumeration QtQuick2::Grid::effectiveHorizontalItemAlignment
+
+ Sets the horizontal and vertical alignment of items in the Grid. By default,
+ the items are vertically aligned to the top. Horizontal
+ alignment follows the layoutDirection of the Grid, for example when having a layoutDirection
+ from LeftToRight, the items will be aligned on the left.
+
+ The valid values for \c horizontalItemAlignment are, \c Grid.AlignLeft, \c Grid.AlignRight and
+ \c Grid.AlignHCenter.
+
+ The valid values for \c verticalItemAlignment are \c Grid.AlignTop, \c Grid.AlignBottom
+ and \c Grid.AlignVCenter.
+
+ The below images show three examples of how to align items.
+
+ \table
+ \row
+ \li
+ \li \inlineimage gridLayout_aligntopleft.png
+ \li \inlineimage gridLayout_aligntop.png
+ \li \inlineimage gridLayout_aligncenter.png
+ \row
+ \li Horizontal alignment
+ \li AlignLeft
+ \li AlignHCenter
+ \li AlignHCenter
+ \row
+ \li Vertical alignment
+ \li AlignTop
+ \li AlignTop
+ \li AlignVCenter
+ \endtable
+
+
+ When mirroring the layout using either the attached property LayoutMirroring::enabled or
+ by setting the layoutDirection, the horizontal alignment of items will be mirrored as well.
+ However, the property \c horizontalItemAlignment will remain unchanged.
+ To query the effective horizontal alignment of items, use the read-only property
+ \c effectiveHorizontalItemAlignment.
+
+ \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+QQuickGrid::HAlignment QQuickGrid::hItemAlign() const
+{
+ return m_hItemAlign;
+}
+void QQuickGrid::setHItemAlign(HAlignment align)
+{
+ if (m_hItemAlign != align) {
+ m_hItemAlign = align;
+ prePositioning();
+ emit horizontalAlignmentChanged(align);
+ emit effectiveHorizontalAlignmentChanged(effectiveHAlign());
+ }
+}
+
+QQuickGrid::HAlignment QQuickGrid::effectiveHAlign() const
+{
+ HAlignment effectiveAlignment = m_hItemAlign;
+ if (effectiveLayoutDirection() == Qt::RightToLeft) {
+ switch (hItemAlign()) {
+ case AlignLeft:
+ effectiveAlignment = AlignRight;
+ break;
+ case AlignRight:
+ effectiveAlignment = AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+
+QQuickGrid::VAlignment QQuickGrid::vItemAlign() const
+{
+ return m_vItemAlign;
+}
+void QQuickGrid::setVItemAlign(VAlignment align)
+{
+ if (m_vItemAlign != align) {
+ m_vItemAlign = align;
+ prePositioning();
+ emit verticalAlignmentChanged(align);
+ }
+}
+
void QQuickGrid::doPositioning(QSizeF *contentSize)
{
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
@@ -1362,9 +1456,22 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
for (int i = 0; i < positionedItems.count(); ++i) {
PositionedItem &child = positionedItems[i];
qreal childXOffset = xoffset;
+
+ if (effectiveHAlign() == AlignRight)
+ childXOffset += maxColWidth[curCol] - child.item->width();
+ else if (hItemAlign() == AlignHCenter)
+ childXOffset += (maxColWidth[curCol] - child.item->width())/2.0;
+
if (!d->isLeftToRight())
- childXOffset -= child.item->width();
- positionItem(childXOffset, yoffset, &child);
+ childXOffset -= maxColWidth[curCol];
+
+ qreal alignYOffset = yoffset;
+ if (m_vItemAlign == AlignVCenter)
+ alignYOffset += (maxRowHeight[curRow] - child.item->height())/2.0;
+ else if (m_vItemAlign == AlignBottom)
+ alignYOffset += maxRowHeight[curRow] - child.item->height();
+
+ positionItem(childXOffset, alignYOffset, &child);
if (m_flow == LeftToRight) {
if (d->isLeftToRight())
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index 784efea510..1ff5a7a74c 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -51,8 +51,6 @@
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickBasePositionerPrivate;
@@ -222,6 +220,9 @@ class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+ Q_PROPERTY(HAlignment horizontalItemAlignment READ hItemAlign WRITE setHItemAlign NOTIFY horizontalAlignmentChanged REVISION 1)
+ Q_PROPERTY(HAlignment effectiveHorizontalItemAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1)
+ Q_PROPERTY(VAlignment verticalItemAlignment READ vItemAlign WRITE setVItemAlign NOTIFY verticalAlignmentChanged REVISION 1)
public:
QQuickGrid(QQuickItem *parent=0);
@@ -249,6 +250,22 @@ public:
void setLayoutDirection (Qt::LayoutDirection);
Qt::LayoutDirection effectiveLayoutDirection() const;
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter};
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+
+ HAlignment hItemAlign() const;
+ void setHItemAlign(HAlignment align);
+ HAlignment effectiveHAlign() const;
+
+ VAlignment vItemAlign() const;
+ void setVItemAlign(VAlignment align);
+
Q_SIGNALS:
void rowsChanged();
void columnsChanged();
@@ -257,6 +274,9 @@ Q_SIGNALS:
void effectiveLayoutDirectionChanged();
void rowSpacingChanged();
void columnSpacingChanged();
+ Q_REVISION(1) void horizontalAlignmentChanged(HAlignment alignment);
+ Q_REVISION(1) void effectiveHorizontalAlignmentChanged(HAlignment alignment);
+ Q_REVISION(1) void verticalAlignmentChanged(VAlignment alignment);
protected:
virtual void doPositioning(QSizeF *contentSize);
@@ -270,6 +290,8 @@ private:
bool m_useRowSpacing;
bool m_useColumnSpacing;
Flow m_flow;
+ HAlignment m_hItemAlign;
+ VAlignment m_vItemAlign;
Q_DISABLE_COPY(QQuickGrid)
};
@@ -318,6 +340,4 @@ QML_DECLARE_TYPE(QQuickFlow)
QML_DECLARE_TYPE(QQuickBasePositioner)
QML_DECLARE_TYPEINFO(QQuickBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
#endif // QQUICKPOSITIONERS_P_H
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 2a8c1a3bb9..3c3bd8897b 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -475,7 +475,7 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
}
rectangle->setRadius(d->radius);
- rectangle->setAntialiasing(d->antialiasing);
+ rectangle->setAntialiasing(d->antialiasing || d->radius > 0);
QGradientStops stops;
if (d->gradient) {
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index 911c3fdf8b..2ad144aafd 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -48,8 +48,6 @@
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QQuickPen : public QObject
@@ -178,6 +176,4 @@ QML_DECLARE_TYPE(QQuickGradientStop)
QML_DECLARE_TYPE(QQuickGradient)
QML_DECLARE_TYPE(QQuickRectangle)
-QT_END_HEADER
-
#endif // QQUICKRECTANGLE_P_H
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 4c43b4bf72..35e37d1246 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -41,16 +41,18 @@
#include "qquickrepeater_p.h"
#include "qquickrepeater_p_p.h"
-#include "qquickvisualdatamodel_p.h"
#include <private/qqmlglobal_p.h>
-#include <private/qquicklistaccessor_p.h>
-#include <private/qquickchangeset_p.h>
+#include <private/qqmllistaccessor_p.h>
+#include <private/qqmlchangeset_p.h>
+#include <private/qqmldelegatemodel_p.h>
+
+#include <QtQml/QQmlInfo>
QT_BEGIN_NAMESPACE
QQuickRepeaterPrivate::QQuickRepeaterPrivate()
- : model(0), ownModel(false), inRequest(false), dataSourceIsObject(false), itemCount(0), createFrom(-1)
+ : model(0), ownModel(false), inRequest(false), dataSourceIsObject(false), delegateValidated(false), itemCount(0), createFrom(-1)
{
}
@@ -193,18 +195,18 @@ void QQuickRepeater::setModel(const QVariant &model)
clear();
if (d->model) {
- disconnect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
- disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
-// disconnect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
+ disconnect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
+ disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+// disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
}
d->dataSource = model;
QObject *object = qvariant_cast<QObject*>(model);
d->dataSourceAsObject = object;
d->dataSourceIsObject = object != 0;
- QQuickVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
+ QQmlInstanceModel *vim = 0;
+ if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
if (d->ownModel) {
delete d->model;
d->ownModel = false;
@@ -212,20 +214,20 @@ void QQuickRepeater::setModel(const QVariant &model)
d->model = vim;
} else {
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
if (isComponentComplete())
- static_cast<QQuickVisualDataModel *>(d->model)->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model)->componentComplete();
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
dataModel->setModel(model);
}
if (d->model) {
- connect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
- connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
-// connect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
+ connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
+ connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+// connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
regenerate();
}
emit modelChanged();
@@ -269,7 +271,7 @@ QQmlComponent *QQuickRepeater::delegate() const
{
Q_D(const QQuickRepeater);
if (d->model) {
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
return dataModel->delegate();
}
@@ -279,18 +281,20 @@ QQmlComponent *QQuickRepeater::delegate() const
void QQuickRepeater::setDelegate(QQmlComponent *delegate)
{
Q_D(QQuickRepeater);
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
if (delegate == dataModel->delegate())
return;
if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
}
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
+
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
dataModel->setDelegate(delegate);
regenerate();
emit delegateChanged();
+ d->delegateValidated = false;
}
}
@@ -325,7 +329,7 @@ void QQuickRepeater::componentComplete()
{
Q_D(QQuickRepeater);
if (d->model && d->ownModel)
- static_cast<QQuickVisualDataModel *>(d->model)->componentComplete();
+ static_cast<QQmlDelegateModel *>(d->model)->componentComplete();
QQuickItem::componentComplete();
regenerate();
if (d->model && d->model->count())
@@ -350,6 +354,7 @@ void QQuickRepeater::clear()
QQuickItem *item = d->deletables.at(i);
if (complete)
emit itemRemoved(i, item);
+ item->setParentItem(0);
d->model->release(item);
}
}
@@ -382,8 +387,17 @@ void QQuickRepeaterPrivate::createItems()
inRequest = true;
for (int ii = createFrom; ii < itemCount; ++ii) {
if (!deletables.at(ii)) {
- QQuickItem *item = model->item(ii, false);
+ QObject *object = model->object(ii, false);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (!item) {
+ if (object) {
+ model->release(object);
+ if (!delegateValidated) {
+ delegateValidated = true;
+ QObject* delegate = q->delegate();
+ qmlInfo(delegate ? delegate : q) << q->tr("Delegate must be of Item type");
+ }
+ }
createFrom = ii;
break;
}
@@ -407,19 +421,21 @@ void QQuickRepeaterPrivate::createItems()
inRequest = false;
}
-void QQuickRepeater::createdItem(int, QQuickItem *)
+void QQuickRepeater::createdItem(int, QObject *)
{
Q_D(QQuickRepeater);
if (!d->inRequest)
d->createItems();
}
-void QQuickRepeater::initItem(int, QQuickItem *item)
+void QQuickRepeater::initItem(int, QObject *object)
{
- item->setParentItem(parentItem());
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (item)
+ item->setParentItem(parentItem());
}
-void QQuickRepeater::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
+void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickRepeater);
@@ -435,7 +451,7 @@ void QQuickRepeater::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
int difference = 0;
QHash<int, QVector<QPointer<QQuickItem> > > moved;
- foreach (const QQuickChangeSet::Remove &remove, changeSet.removes()) {
+ foreach (const QQmlChangeSet::Remove &remove, changeSet.removes()) {
int index = qMin(remove.index, d->deletables.count());
int count = qMin(remove.index + remove.count, d->deletables.count()) - index;
if (remove.isMove()) {
@@ -447,8 +463,10 @@ void QQuickRepeater::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
QQuickItem *item = d->deletables.at(index);
d->deletables.remove(index);
emit itemRemoved(index, item);
- if (item)
+ if (item) {
+ item->setParentItem(0);
d->model->release(item);
+ }
--d->itemCount;
}
@@ -456,7 +474,7 @@ void QQuickRepeater::modelUpdated(const QQuickChangeSet &changeSet, bool reset)
}
d->createFrom = -1;
- foreach (const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
+ foreach (const QQmlChangeSet::Insert &insert, changeSet.inserts()) {
int index = qMin(insert.index, d->deletables.count());
if (insert.isMove()) {
QVector<QPointer<QQuickItem> > items = moved.value(insert.moveId);
diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h
index 17153694c9..be9ed7266d 100644
--- a/src/quick/items/qquickrepeater_p.h
+++ b/src/quick/items/qquickrepeater_p.h
@@ -44,11 +44,9 @@
#include "qquickitem.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
-class QQuickChangeSet;
+class QQmlChangeSet;
class QQuickRepeaterPrivate;
class Q_AUTOTEST_EXPORT QQuickRepeater : public QQuickItem
@@ -91,9 +89,9 @@ protected:
void itemChange(ItemChange change, const ItemChangeData &value);
private Q_SLOTS:
- void createdItem(int index, QQuickItem *item);
- void initItem(int, QQuickItem *item);
- void modelUpdated(const QQuickChangeSet &changeSet, bool reset);
+ void createdItem(int index, QObject *item);
+ void initItem(int, QObject *item);
+ void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
private:
Q_DISABLE_COPY(QQuickRepeater)
@@ -104,6 +102,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickRepeater)
-QT_END_HEADER
-
#endif // QQUICKREPEATER_P_H
diff --git a/src/quick/items/qquickrepeater_p_p.h b/src/quick/items/qquickrepeater_p_p.h
index a187aea39c..f220eb4fcb 100644
--- a/src/quick/items/qquickrepeater_p_p.h
+++ b/src/quick/items/qquickrepeater_p_p.h
@@ -61,7 +61,7 @@
QT_BEGIN_NAMESPACE
class QQmlContext;
-class QQuickVisualModel;
+class QQmlInstanceModel;
class QQuickRepeaterPrivate : public QQuickItemPrivate
{
Q_DECLARE_PUBLIC(QQuickRepeater)
@@ -73,12 +73,13 @@ public:
private:
void createItems();
- QQuickVisualModel *model;
+ QQmlInstanceModel *model;
QVariant dataSource;
QQmlGuard<QObject> dataSourceAsObject;
bool ownModel : 1;
bool inRequest : 1;
bool dataSourceIsObject : 1;
+ bool delegateValidated : 1;
int itemCount;
int createFrom;
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index b10785f60e..264c444229 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -50,8 +50,6 @@
#include <QtQuick/private/qquickpixmapcache_p.h>
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickScaleGrid : public QObject
@@ -126,6 +124,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickScaleGrid)
-QT_END_HEADER
-
#endif // QQUICKSCALEGRID_P_P_H
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 7c7d8a6eab..33a831acad 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -54,20 +54,29 @@ QT_BEGIN_NAMESPACE
\instantiates QQuickScreenAttached
\inqmlmodule QtQuick.Window 2
\ingroup qtquick-visual-utility
- \brief The Screen attached object provides information about the Screen an Item is displayed on.
+ \brief The Screen attached object provides information about the Screen an Item or Window is displayed on.
- The Screen attached object is only valid inside Item or Item derived types, after component completion.
- Inside these items it refers to the screen that the item is currently being displayed on.
+ The Screen attached object is valid inside Item or Item derived types,
+ after component completion. Inside these items it refers to the screen that
+ the item is currently being displayed on.
+
+ The attached object is also valid inside Window or Window derived types,
+ after component completion. In that case it refers to the screen where the
+ Window was created. It is generally better to access the Screen from the
+ relevant Item instead, because on a multi-screen desktop computer, the user
+ can drag a Window into a position where it spans across multiple screens.
+ In that case some Items will be on one screen, and others on a different
+ screen.
To use this type, you will need to import the module with the following line:
\code
import QtQuick.Window 2.0
\endcode
+ It is a separate import in order to allow you to have a QML environment
+ without access to window system features.
- Note that the Screen type is not valid at Component.onCompleted, because the Item has not been displayed on
- a screen by this time.
-
- Restricting this import will allow you to have a QML environment without access to window system features.
+ Note that the Screen type is not valid at Component.onCompleted, because
+ the Item or Window has not been displayed on a screen by this time.
*/
/*!
@@ -86,13 +95,32 @@ QT_BEGIN_NAMESPACE
\qmlattachedproperty Qt::ScreenOrientation QtQuick.Window2::Screen::primaryOrientation
\readonly
- This contains the primary orientation of the screen.
+ This contains the primary orientation of the screen. If the
+ screen's height is greater than its width, then the orientation is
+ Qt.PortraitOrientation; otherwise it is Qt.LandscapeOrientation.
+
+ If you are designing an application which changes its layout depending on
+ device orientation, you probably want to use primaryOrientation to
+ determine the layout. That is because on a desktop computer, you can expect
+ primaryOrientation to change when the user rotates the screen via the
+ operating system's control panel, even if the computer does not contain an
+ accelerometer. Likewise on most handheld computers which do have
+ accelerometers, the operating system will rotate the whole screen
+ automatically, so again you will see the primaryOrientation change.
*/
/*!
\qmlattachedproperty Qt::ScreenOrientation QtQuick.Window2::Screen::orientation
\readonly
- This contains the current orientation of the screen.
+ This contains the current orientation of the screen, from the accelerometer
+ (if any). On a desktop computer, this value typically does not change.
+
+ If primaryOrientation == orientation, it means that the screen
+ automatically rotates all content which is displayed, depending on how you
+ hold it. But if orientation changes while primaryOrientation does NOT
+ change, then probably you are using a device which does not rotate its own
+ display. In that case you may need to use \l Item.rotation or
+ \l Item.transform to rotate your content.
*/
/*!
\qmlattachedmethod int QtQuick.Window2::Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
@@ -112,6 +140,10 @@ QQuickScreenAttached::QQuickScreenAttached(QObject* attachee)
if (m_attachee->window()) //It might not be assigned to a window yet
windowChanged(m_attachee->window());
+ } else {
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(attachee);
+ if (window)
+ windowChanged(window);
}
}
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 014fc0709b..98f38b7154 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -47,8 +47,6 @@
#include <QSize>
#include <private/qqmlglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -104,6 +102,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPEINFO(QQuickScreen, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
#endif
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 6abb41b737..5c3dcf4e41 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -52,8 +52,6 @@
#include <QtCore/qpointer.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
const char *qtPositionAttributeName();
@@ -193,6 +191,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSHADEREFFECT_P_H
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index 15f4d02c12..9c19b8e6e6 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -51,8 +51,6 @@
#ifndef QQUICKSHADEREFFECTMESH_P_H
#define QQUICKSHADEREFFECTMESH_P_H
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QSGGeometry;
@@ -101,6 +99,4 @@ inline QColor qt_premultiply_color(const QColor &c)
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSHADEREFFECTMESH_P_H
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
index db21d06f58..a6854526fa 100644
--- a/src/quick/items/qquickshadereffectnode_p.h
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -51,8 +51,6 @@
#include <QtCore/qsharedpointer.h>
#include <QtCore/qpointer.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
struct QQuickShaderEffectMaterialKey {
@@ -147,6 +145,4 @@ private Q_SLOTS:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSHADEREFFECTNODE_P_H
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index bdfef7ca88..59b788643a 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -53,6 +53,7 @@
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+DEFINE_BOOL_CONFIG_OPTION(qmlFboFlushBeforeDetach, QML_FBO_FLUSH_BEFORE_DETACH)
namespace
{
@@ -75,6 +76,8 @@ namespace
BindableFbo::~BindableFbo()
{
+ if (qmlFboFlushBeforeDetach())
+ glFlush();
if (m_depthStencil)
m_depthStencil->detach();
}
@@ -128,6 +131,7 @@ void QQuickShaderEffectSourceNode::markDirtyTexture()
QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource)
: QSGDynamicTexture()
, m_item(0)
+ , m_device_pixel_ratio(1)
, m_format(GL_RGBA)
, m_renderer(0)
, m_fbo(0)
@@ -310,6 +314,7 @@ void QQuickShaderEffectTexture::grab()
m_renderer = m_context->createRenderer();
connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
}
+ m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
bool deleteFboLater = false;
@@ -957,11 +962,12 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
: m_textureSize;
Q_ASSERT(!textureSize.isEmpty());
+ QQuickItemPrivate *d = static_cast<QQuickItemPrivate *>(QObjectPrivate::get(this));
+
// Crate large textures on high-dpi displays.
- if (sourceItem() && sourceItem()->window())
- textureSize *= sourceItem()->window()->devicePixelRatio();
+ if (sourceItem())
+ textureSize *= d->window->devicePixelRatio();
- QQuickItemPrivate *d = static_cast<QQuickItemPrivate *>(QObjectPrivate::get(this));
const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
// Keep power-of-two by doubling the size.
while (textureSize.width() < minTextureSize.width())
@@ -969,6 +975,7 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
while (textureSize.height() < minTextureSize.height())
textureSize.rheight() *= 2;
+ m_texture->setDevicePixelRatio(d->window->devicePixelRatio());
m_texture->setSize(textureSize);
m_texture->setRecursive(m_recursive);
m_texture->setFormat(GLenum(m_format));
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 5c9427adde..f391ed2389 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -55,8 +55,6 @@
#define QSG_DEBUG_FBO_OVERLAY
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QSGNode;
@@ -113,6 +111,8 @@ public:
bool recursive() const { return bool(m_recursive); }
void setRecursive(bool recursive);
+ void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
+
void scheduleUpdate();
QImage toImage() const;
@@ -130,6 +130,7 @@ private:
QSGNode *m_item;
QRectF m_rect;
QSize m_size;
+ qreal m_device_pixel_ratio;
GLenum m_format;
QSGRenderer *m_renderer;
@@ -257,6 +258,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSHADEREFFECTSOURCE_P_H
diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp
index 13593384d8..b4138308f6 100644
--- a/src/quick/items/qquicksprite.cpp
+++ b/src/quick/items/qquicksprite.cpp
@@ -254,8 +254,15 @@ int QQuickSprite::variedDuration() const //Deals with precedence when multiple d
void QQuickSprite::startImageLoading()
{
m_pix.clear(this);
- if (!m_source.isEmpty())
- m_pix.load(qmlEngine(this), m_source);
+ if (!m_source.isEmpty()) {
+ QQmlEngine *e = qmlEngine(this);
+ if (!e) { //If not created in QML, you must set the QObject parent to the QML element so this can work
+ e = qmlEngine(parent());
+ if (!e)
+ qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work";
+ }
+ m_pix.load(e, m_source);
+ }
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
index dce28e888b..a85059e8d6 100644
--- a/src/quick/items/qquicksprite_p.h
+++ b/src/quick/items/qquicksprite_p.h
@@ -50,8 +50,6 @@
#include "qquickspriteengine_p.h"
#include <QDebug>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickSprite : public QQuickStochasticState
@@ -316,5 +314,4 @@ private:
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // QQUICKSPRITE_P_H
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 6dc4cf4436..aa93d31cf7 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -328,6 +328,7 @@ QQuickPixmap::Status QQuickSpriteEngine::status()//Composed status of all Sprite
null = loading = ready = 0;
foreach (QQuickSprite* s, m_sprites) {
switch (s->m_pix.status()) {
+ // ### Maybe add an error message here, because this null shouldn't be reached but when it does, the image fails without an error message.
case QQuickPixmap::Null : null++; break;
case QQuickPixmap::Loading : loading++; break;
case QQuickPixmap::Error : return QQuickPixmap::Error;
@@ -429,7 +430,7 @@ QImage QQuickSpriteEngine::assembledImage()
}
//maxFrames is max number in a line of the texture
- QImage image(w, h, QImage::Format_ARGB32);
+ QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QPainter p(&image);
int y = 0;
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 612a2b4c2d..768b5e4a6e 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -53,8 +53,6 @@
#include <private/qquickpixmapcache_p.h>
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickSprite;
@@ -323,6 +321,4 @@ inline int spriteCount(QQmlListProperty<QQuickSprite> *p)
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSPRITEENGINE_P_H
diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h
index b07d177745..b954a4464f 100644
--- a/src/quick/items/qquickspritesequence_p.h
+++ b/src/quick/items/qquickspritesequence_p.h
@@ -45,8 +45,6 @@
#include <QtQuick/QQuickItem>
#include <QTime>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QSGContext;
@@ -145,6 +143,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKSPRITESEQUENCE_P_H
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
index d43420f266..9ee0d591da 100644
--- a/src/quick/items/qquickstateoperations_p.h
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -49,8 +49,6 @@
#include <QtQml/qqmlscriptstring.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickParentChangePrivate;
@@ -213,7 +211,5 @@ QML_DECLARE_TYPE(QQuickParentChange)
QML_DECLARE_TYPE(QQuickAnchorSet)
QML_DECLARE_TYPE(QQuickAnchorChanges)
-QT_END_HEADER
-
#endif // QQUICKSTATEOPERATIONS_P_H
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 917eaeadd8..9a90b408c3 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -312,6 +312,8 @@ qreal QQuickTextPrivate::getImplicitHeight() const
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
+
+ On HighDpi "retina" displays this property is ignored and QtRendering is always used.
*/
QQuickText::RenderType QQuickText::renderType() const
{
@@ -2234,7 +2236,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
node = static_cast<QQuickTextNode *>(oldNode);
}
- node->setUseNativeRenderer(d->renderType == NativeRendering);
+ node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
node->deleteContent();
node->setMatrix(QMatrix4x4());
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index ba0260c5c7..03b436b3fb 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -46,8 +46,6 @@
#include <private/qtquickglobal_p.h>
#include <QtGui/qtextoption.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickTextPrivate;
@@ -295,6 +293,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickText)
QML_DECLARE_TYPE(QQuickTextLine)
-QT_END_HEADER
-
#endif // QQUICKTEXT_P_H
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 02aeaa7e35..9625aa5d5e 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -359,7 +359,7 @@ void QQuickTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode
if (mode != QTextCursor::KeepAnchor) {
selectedWordOnDoubleClick = QTextCursor();
- selectedBlockOnTrippleClick = QTextCursor();
+ selectedBlockOnTripleClick = QTextCursor();
}
}
@@ -527,18 +527,18 @@ void QQuickTextControlPrivate::extendBlockwiseSelection(int suggestedNewPosition
Q_Q(QQuickTextControl);
// if inside the initial selected line keep that
- if (suggestedNewPosition >= selectedBlockOnTrippleClick.selectionStart()
- && suggestedNewPosition <= selectedBlockOnTrippleClick.selectionEnd()) {
- q->setTextCursor(selectedBlockOnTrippleClick);
+ if (suggestedNewPosition >= selectedBlockOnTripleClick.selectionStart()
+ && suggestedNewPosition <= selectedBlockOnTripleClick.selectionEnd()) {
+ q->setTextCursor(selectedBlockOnTripleClick);
return;
}
- if (suggestedNewPosition < selectedBlockOnTrippleClick.position()) {
- cursor.setPosition(selectedBlockOnTrippleClick.selectionEnd());
+ if (suggestedNewPosition < selectedBlockOnTripleClick.position()) {
+ cursor.setPosition(selectedBlockOnTripleClick.selectionEnd());
cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
} else {
- cursor.setPosition(selectedBlockOnTrippleClick.selectionStart());
+ cursor.setPosition(selectedBlockOnTripleClick.selectionStart());
cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
@@ -586,6 +586,7 @@ QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent)
qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SIGNAL(textChanged()));
qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SLOT(_q_updateCurrentCharFormatAndSelection()));
qmlobject_connect(doc, QTextDocument, SIGNAL(cursorPositionChanged(QTextCursor)), this, QQuickTextControl, SLOT(_q_emitCursorPosChanged(QTextCursor)));
+ connect(doc, &QTextDocument::contentsChange, this, &QQuickTextControl::contentsChange);
layout->setProperty("cursorWidth", textCursorWidth);
@@ -791,8 +792,8 @@ void QQuickTextControl::timerEvent(QTimerEvent *e)
d->cursorOn = !d->cursorOn;
d->repaintCursor();
- } else if (e->timerId() == d->trippleClickTimer.timerId()) {
- d->trippleClickTimer.stop();
+ } else if (e->timerId() == d->tripleClickTimer.timerId()) {
+ d->tripleClickTimer.stop();
}
}
@@ -1022,17 +1023,17 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po
commitPreedit();
#endif
- if (trippleClickTimer.isActive()
- && ((pos - trippleClickPoint).toPoint().manhattanLength() < qApp->styleHints()->startDragDistance())) {
+ if (tripleClickTimer.isActive()
+ && ((pos - tripleClickPoint).toPoint().manhattanLength() < qApp->styleHints()->startDragDistance())) {
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
- selectedBlockOnTrippleClick = cursor;
+ selectedBlockOnTripleClick = cursor;
anchorOnMousePress = QString();
- trippleClickTimer.stop();
+ tripleClickTimer.stop();
} else {
int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
if (cursorPos == -1) {
@@ -1046,7 +1047,7 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po
selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
}
- if (selectedBlockOnTrippleClick.hasSelection())
+ if (selectedBlockOnTripleClick.hasSelection())
extendBlockwiseSelection(cursorPos);
else if (selectedWordOnDoubleClick.hasSelection())
extendWordwiseSelection(cursorPos, pos.x());
@@ -1079,7 +1080,7 @@ void QQuickTextControlPrivate::mouseMoveEvent(QMouseEvent *e, const QPointF &mou
if (!(mousePressed
|| editable
|| selectedWordOnDoubleClick.hasSelection()
- || selectedBlockOnTrippleClick.hasSelection()))
+ || selectedBlockOnTripleClick.hasSelection()))
return;
const QTextCursor oldSelection = cursor;
@@ -1114,7 +1115,7 @@ void QQuickTextControlPrivate::mouseMoveEvent(QMouseEvent *e, const QPointF &mou
selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
}
- if (selectedBlockOnTrippleClick.hasSelection())
+ if (selectedBlockOnTripleClick.hasSelection())
extendBlockwiseSelection(newCursorPos);
else if (selectedWordOnDoubleClick.hasSelection())
extendWordwiseSelection(newCursorPos, mouseX);
@@ -1219,8 +1220,8 @@ void QQuickTextControlPrivate::mouseDoubleClickEvent(QMouseEvent *e, const QPoin
cursorIsFocusIndicator = false;
selectedWordOnDoubleClick = cursor;
- trippleClickPoint = pos;
- trippleClickTimer.start(qApp->styleHints()->mouseDoubleClickInterval(), q);
+ tripleClickPoint = pos;
+ tripleClickTimer.start(qApp->styleHints()->mouseDoubleClickInterval(), q);
if (doEmit) {
selectionChanged();
#ifndef QT_NO_CLIPBOARD
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 84d6fcce52..7ec8a68b4c 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -63,8 +63,6 @@
#include <QtGui/qclipboard.h>
#include <QtCore/qmimedata.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -140,6 +138,7 @@ public Q_SLOTS:
Q_SIGNALS:
void textChanged();
+ void contentsChange(int from, int charsRemoved, int charsAdded);
void undoAvailable(bool b);
void redoAvailable(bool b);
void currentCharFormatChanged(const QTextCharFormat &format);
@@ -196,6 +195,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQuickTextControl_H
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index 059ccd36bf..fbb88bd255 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QTEXTCONTROL_P_P_H
-#define QTEXTCONTROL_P_P_H
+#ifndef QQUICKTEXTCONTROL_P_P_H
+#define QQUICKTEXTCONTROL_P_P_H
//
// W A R N I N G
@@ -126,7 +126,7 @@ public:
void cancelPreedit();
#endif
- QPointF trippleClickPoint;
+ QPointF tripleClickPoint;
QPointF mousePressPos;
QTextCharFormat lastCharFormat;
@@ -134,12 +134,12 @@ public:
QTextDocument *doc;
QTextCursor cursor;
QTextCursor selectedWordOnDoubleClick;
- QTextCursor selectedBlockOnTrippleClick;
+ QTextCursor selectedBlockOnTripleClick;
QString anchorOnMousePress;
QString linkToCopy;
QBasicTimer cursorBlinkTimer;
- QBasicTimer trippleClickTimer;
+ QBasicTimer tripleClickTimer;
#ifndef QT_NO_IM
int preeditCursor;
diff --git a/src/quick/items/qquickwindowmanager_p.h b/src/quick/items/qquicktextdocument.cpp
index 94142a9d90..e29e48c5d0 100644
--- a/src/quick/items/qquickwindowmanager_p.h
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -39,49 +39,33 @@
**
****************************************************************************/
-#ifndef QQUICKWINDOWMANAGER_P_H
-#define QQUICKWINDOWMANAGER_P_H
+#include "qquicktextdocument.h"
-#include <QtGui/QImage>
-#include <private/qtquickglobal_p.h>
+#include "qquicktextedit_p.h"
+#include "qquicktextedit_p_p.h"
+#include "qquicktext_p_p.h"
QT_BEGIN_NAMESPACE
-class QQuickWindow;
-class QSGContext;
-class QAnimationDriver;
-
-class Q_QUICK_PRIVATE_EXPORT QQuickWindowManager
+class QQuickTextDocumentPrivate : public QObjectPrivate
{
public:
- virtual ~QQuickWindowManager();
-
- virtual void show(QQuickWindow *window) = 0;
- virtual void hide(QQuickWindow *window) = 0;
-
- virtual void windowDestroyed(QQuickWindow *window) = 0;
-
- virtual void exposureChanged(QQuickWindow *window) = 0;
- virtual QImage grab(QQuickWindow *window) = 0;
- virtual void resize(QQuickWindow *window, const QSize &size) = 0;
-
- virtual void update(QQuickWindow *window) = 0;
- virtual void maybeUpdate(QQuickWindow *window) = 0;
-
- virtual QAnimationDriver *animationDriver() const = 0;
-
- virtual QSGContext *sceneGraphContext() const = 0;
-
- virtual void releaseResources() = 0;
+ QPointer<QTextDocument> document;
+};
- // ### make this less of a singleton
- static QQuickWindowManager *instance();
- static void setInstance(QQuickWindowManager *instance);
+QQuickTextDocument::QQuickTextDocument(QQuickItem *parent)
+ : QObject(*(new QQuickTextDocumentPrivate), parent)
+{
+ Q_D(QQuickTextDocument);
+ Q_ASSERT(parent);
+ Q_ASSERT(qobject_cast<QQuickTextEdit*>(parent));
+ d->document = QPointer<QTextDocument>(qobject_cast<QQuickTextEdit*>(parent)->d_func()->document);
+}
-private:
- static QQuickWindowManager *s_instance;
-};
+QTextDocument* QQuickTextDocument::textDocument() const
+{
+ Q_D(const QQuickTextDocument);
+ return d->document.data();
+}
QT_END_NAMESPACE
-
-#endif // QQUICKWINDOWMANAGER_P_H
diff --git a/src/quick/items/qquicktextdocument.h b/src/quick/items/qquicktextdocument.h
new file mode 100644
index 0000000000..25d3bbeaf0
--- /dev/null
+++ b/src/quick/items/qquicktextdocument.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKTEXTDOCUMENT_H
+#define QQUICKTEXTDOCUMENT_H
+
+#include <QtGui/QTextDocument>
+#include <QtQuick/QQuickItem>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickTextDocument
+ \since 5.1
+ \brief The QQuickTextDocument class provides access to the QTextDocument of QQuickTextEdit
+ \inmodule QtQuick
+
+ This class provides access to the QTextDocument of QQuickTextEdit elements.
+ This is provided to allow usage of the \l{Rich Text Processing} functionalities of Qt.
+ You are not allowed to modify the document, but it can be used to output content, for example with \l{QTextDocumentWriter}),
+ or provide additional formatting, for example with \l{QSyntaxHighlighter}.
+
+ The class has to be used from C++ directly, using the property of the \l TextEdit.
+
+ Warning: The QTextDocument provided is used internally by QtQuick elements to provide text manipulation primitives.
+ You are not allowed to perform any modification of the internal state of the QTextDocument. If you do, the element
+ in question may stop functioning or crash.
+*/
+
+class QQuickTextDocumentPrivate;
+class Q_QUICK_EXPORT QQuickTextDocument : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickTextDocument(QQuickItem *parent);
+ QTextDocument *textDocument() const;
+
+private:
+ Q_DISABLE_COPY(QQuickTextDocument)
+ Q_DECLARE_PRIVATE(QQuickTextDocument)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTextDocument)
+
+#endif
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index d543b6bd41..506b4caa52 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -46,6 +46,7 @@
#include "qquickevents_p_p.h"
#include "qquickwindow.h"
#include "qquicktextnode_p.h"
+#include "qquicktextnodeengine_p.h"
#include "qquicktextutil_p.h"
#include <QtQuick/qsgsimplerectnode.h>
@@ -55,12 +56,14 @@
#include <QtGui/qpainter.h>
#include <QtGui/qtextobject.h>
#include <QtCore/qmath.h>
+#include <QtCore/qalgorithms.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qtextengine_p.h>
#include <private/qsgadaptationlayer_p.h>
+#include "qquicktextdocument.h"
QT_BEGIN_NAMESPACE
@@ -117,6 +120,11 @@ TextEdit {
The link must be in rich text or HTML format and the
\a link string provides access to the particular link.
*/
+
+// This is a pretty arbitrary figure. The idea is that we don't want to break down the document
+// into text nodes corresponding to a text block each so that the glyph node grouping doesn't become pointless.
+static const int nodeBreakingSize = 300;
+
QQuickTextEdit::QQuickTextEdit(QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickTextEditPrivate), parent)
{
@@ -360,6 +368,8 @@ void QQuickTextEdit::setTextFormat(TextFormat format)
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
+
+ On HighDpi "retina" displays this property is ignored and QtRendering is always used.
*/
QQuickTextEdit::RenderType QQuickTextEdit::renderType() const
{
@@ -409,7 +419,7 @@ void QQuickTextEdit::setFont(const QFont &font)
moveCursorDelegate();
}
updateSize();
- updateDocument();
+ updateWholeDocument();
#ifndef QT_NO_IM
updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
#endif
@@ -445,7 +455,7 @@ void QQuickTextEdit::setColor(const QColor &color)
return;
d->color = color;
- updateDocument();
+ updateWholeDocument();
emit colorChanged(d->color);
}
@@ -467,7 +477,7 @@ void QQuickTextEdit::setSelectionColor(const QColor &color)
return;
d->selectionColor = color;
- updateDocument();
+ updateWholeDocument();
emit selectionColorChanged(d->selectionColor);
}
@@ -489,7 +499,7 @@ void QQuickTextEdit::setSelectedTextColor(const QColor &color)
return;
d->selectedTextColor = color;
- updateDocument();
+ updateWholeDocument();
emit selectedTextColorChanged(d->selectedTextColor);
}
@@ -634,6 +644,13 @@ void QQuickTextEditPrivate::mirrorChange()
}
}
+#ifndef QT_NO_IM
+Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const
+{
+ return inputMethodHints | Qt::ImhMultiLine;
+}
+#endif
+
QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const
{
Q_D(const QQuickTextEdit);
@@ -1089,7 +1106,7 @@ void QQuickTextEdit::setFocusOnPress(bool on)
\qmlproperty bool QtQuick2::TextEdit::persistentSelection
Whether the TextEdit should keep the selection visible when it loses active focus to another
- item in the scene. By default this is set to true;
+ item in the scene. By default this is set to false.
*/
bool QQuickTextEdit::persistentSelection() const
{
@@ -1197,6 +1214,7 @@ void QQuickTextEdit::geometryChanged(const QRectF &newGeometry,
Q_D(QQuickTextEdit);
if (newGeometry.width() != oldGeometry.width() && widthValid() && !d->inLayout) {
updateSize();
+ updateWholeDocument();
moveCursorDelegate();
}
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
@@ -1230,6 +1248,44 @@ void QQuickTextEdit::componentComplete()
if (d->cursorComponent && isCursorVisible())
QQuickTextUtil::createCursor(d);
}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::selectByKeyboard
+ \since QtQuick 2.1
+
+ Defaults to true when the editor is editable, and false
+ when read-only.
+
+ If true, the user can use the keyboard to select text
+ even if the editor is read-only. If false, the user
+ cannot use the keyboard to select text even if the
+ editor is editable.
+
+ \sa readOnly
+*/
+bool QQuickTextEdit::selectByKeyboard() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->selectByKeyboardSet)
+ return d->selectByKeyboard;
+ return !isReadOnly();
+}
+
+void QQuickTextEdit::setSelectByKeyboard(bool on)
+{
+ Q_D(QQuickTextEdit);
+ bool was = selectByKeyboard();
+ if (!d->selectByKeyboardSet || was != on) {
+ d->selectByKeyboardSet = true;
+ d->selectByKeyboard = on;
+ if (on)
+ d->control->setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByKeyboard);
+ else
+ d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByKeyboard);
+ emit selectByKeyboardChanged(on);
+ }
+}
+
/*!
\qmlproperty bool QtQuick2::TextEdit::selectByMouse
@@ -1308,8 +1364,12 @@ void QQuickTextEdit::setReadOnly(bool r)
Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
if (d->selectByMouse)
flags = flags | Qt::TextSelectableByMouse;
+ if (d->selectByKeyboardSet && d->selectByKeyboard)
+ flags = flags | Qt::TextSelectableByKeyboard;
+ else if (!d->selectByKeyboardSet && !r)
+ flags = flags | Qt::TextSelectableByKeyboard;
if (!r)
- flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
+ flags = flags | Qt::TextEditable;
d->control->setTextInteractionFlags(flags);
if (!r)
d->control->moveCursor(QTextCursor::End);
@@ -1319,6 +1379,8 @@ void QQuickTextEdit::setReadOnly(bool r)
#endif
q_canPasteChanged();
emit readOnlyChanged(r);
+ if (!d->selectByKeyboardSet)
+ emit selectByKeyboardChanged(!r);
}
bool QQuickTextEdit::isReadOnly() const
@@ -1440,7 +1502,7 @@ void QQuickTextEdit::select(int start, int end)
d->control->setTextCursor(cursor);
// QTBUG-11100
- updateSelectionMarkers();
+ updateSelection();
}
/*!
@@ -1531,7 +1593,7 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (d->focusOnPress){
bool hadActiveFocus = hasActiveFocus();
- forceActiveFocus();
+ forceActiveFocus(Qt::MouseFocusReason);
// re-open input panel on press if already focused
#ifndef QT_NO_IM
if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
@@ -1593,30 +1655,7 @@ void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
if (wasComposing != isInputMethodComposing())
emit inputMethodComposingChanged();
}
-#endif // QT_NO_IM
-void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
-{
- Q_D(QQuickTextEdit);
- if (change == ItemActiveFocusHasChanged) {
- setCursorVisible(value.boolValue);
- QFocusEvent focusEvent(value.boolValue ? QEvent::FocusIn : QEvent::FocusOut);
- d->control->processEvent(&focusEvent, QPointF(-d->xoff, -d->yoff));
- if (value.boolValue) {
- q_updateAlignment();
-#ifndef QT_NO_IM
- connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
- this, SLOT(q_updateAlignment()));
- } else {
- disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
- this, SLOT(q_updateAlignment()));
-#endif
- }
- }
- QQuickItem::itemChange(change, value);
-}
-
-#ifndef QT_NO_IM
/*!
\overload
Returns the value of the given \a property.
@@ -1631,7 +1670,7 @@ QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
v = (bool)(flags() & ItemAcceptsInputMethod);
break;
case Qt::ImHints:
- v = (int)inputMethodHints();
+ v = (int)d->effectiveInputMethodHints();
break;
default:
v = d->control->inputMethodQuery(property);
@@ -1650,6 +1689,15 @@ void QQuickTextEdit::triggerPreprocess()
update();
}
+typedef QQuickTextEditPrivate::Node TextNode;
+typedef QList<TextNode*>::iterator TextNodeIterator;
+
+
+static bool comesBefore(TextNode* n1, TextNode* n2)
+{
+ return n1->startPos() < n2->startPos();
+}
+
QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData);
@@ -1663,45 +1711,144 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
d->updateType = QQuickTextEditPrivate::UpdateNone;
- QSGNode *currentNode = oldNode;
- if (oldNode == 0 || d->documentDirty) {
- d->documentDirty = false;
+ QSGTransformNode *rootNode = static_cast<QSGTransformNode *>(oldNode);
+ TextNodeIterator nodeIterator = d->textNodeMap.begin();
+ while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty())
+ ++nodeIterator;
- QQuickTextNode *node = 0;
- if (oldNode == 0) {
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
- currentNode = node;
- } else {
- node = static_cast<QQuickTextNode *>(oldNode);
+
+ if (!oldNode || nodeIterator < d->textNodeMap.end()) {
+
+ if (!oldNode)
+ rootNode = new QSGTransformNode;
+
+ int firstDirtyPos = 0;
+ if (nodeIterator != d->textNodeMap.end()) {
+ firstDirtyPos = (*nodeIterator)->startPos();
+ do {
+ rootNode->removeChildNode((*nodeIterator)->textNode());
+ delete (*nodeIterator)->textNode();
+ delete *nodeIterator;
+ nodeIterator = d->textNodeMap.erase(nodeIterator);
+ } while (nodeIterator != d->textNodeMap.end() && (*nodeIterator)->dirty());
}
- node->setUseNativeRenderer(d->renderType == NativeRendering);
- node->deleteContent();
- node->setMatrix(QMatrix4x4());
+ // FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
+ if (d->frameDecorationsNode) {
+ rootNode->removeChildNode(d->frameDecorationsNode);
+ delete d->frameDecorationsNode;
+ }
+ d->frameDecorationsNode = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
+ d->frameDecorationsNode->initEngine(QColor(), QColor(), QColor());
+
+
+ QQuickTextNode *node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
+ node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
+ node->initEngine(d->color, d->selectedTextColor, d->selectionColor);
+
+
+ int sizeCounter = 0;
+ int prevBlockStart = firstDirtyPos;
+ QPointF basePosition(d->xoff, d->yoff);
+ QPointF nodeOffset;
+ TextNode *firstCleanNode = (nodeIterator != d->textNodeMap.end()) ? *nodeIterator : 0;
+
+ QList<QTextFrame *> frames;
+ frames.append(d->document->rootFrame());
+
+ while (!frames.isEmpty()) {
+ QTextFrame *textFrame = frames.takeFirst();
+ frames.append(textFrame->childFrames());
+ d->frameDecorationsNode->m_engine->addFrameDecorations(d->document, textFrame);
+
+ if (textFrame->firstPosition() > textFrame->lastPosition()
+ && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
+ QRectF rect = d->document->documentLayout()->frameBoundingRect(textFrame);
+
+ if (!node->m_engine->hasContents()) {
+ nodeOffset = rect.topLeft();
+ QMatrix4x4 transformMatrix;
+ transformMatrix.translate(nodeOffset.x(), nodeOffset.y());
+ node->setMatrix(transformMatrix);
+ }
+ const int pos = textFrame->firstPosition() - 1;
+ QTextBlock block = textFrame->firstCursorPosition().block();
+ node->m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ node->m_engine->addTextObject(QPointF(0, 0), block.charFormat(), QQuickTextNodeEngine::Unselected, d->document,
+ pos, textFrame->frameFormat().position());
+ } else {
+
+ QTextFrame::iterator it = textFrame->begin();
+
+ while (!it.atEnd()) {
+ QTextBlock block = it.currentBlock();
+ ++it;
+ if (block.position() < firstDirtyPos)
+ continue;
+
+ if (!node->m_engine->hasContents()) {
+ nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
+ QMatrix4x4 transformMatrix;
+ transformMatrix.translate(nodeOffset.x(), nodeOffset.y());
+ node->setMatrix(transformMatrix);
+ }
+
+ node->m_engine->addTextBlock(d->document, block, basePosition - nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
+ sizeCounter += block.length();
+
+ if ((it.atEnd() && frames.isEmpty()) || (firstCleanNode && block.next().position() >= firstCleanNode->startPos())) // last node that needed replacing or last block of the last frame
+ break;
+
+ if (sizeCounter > nodeBreakingSize) {
+ sizeCounter = 0;
+ node->m_engine->addToSceneGraph(node, QQuickText::Normal, QColor());
+ nodeIterator = d->textNodeMap.insert(nodeIterator, new TextNode(prevBlockStart, node));
+ ++nodeIterator;
+ rootNode->appendChildNode(node);
+ prevBlockStart = block.next().position();
+ node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
+ node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
+ node->initEngine(d->color, d->selectedTextColor, d->selectionColor);
+ }
+ }
+ }
+ }
+ node->m_engine->addToSceneGraph(node, QQuickText::Normal, QColor());
+ nodeIterator = d->textNodeMap.insert(nodeIterator, new TextNode(prevBlockStart, node));
+ ++nodeIterator;
+ rootNode->appendChildNode(node);
+ d->frameDecorationsNode->m_engine->addToSceneGraph(d->frameDecorationsNode, QQuickText::Normal, QColor());
+ // Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front.
+ rootNode->prependChildNode(d->frameDecorationsNode);
+
+ Q_ASSERT(nodeIterator == d->textNodeMap.end() || (*nodeIterator) == firstCleanNode);
+ // Update the position of the subsequent text blocks.
+ if (firstCleanNode) {
+ QPointF oldOffset = firstCleanNode->textNode()->matrix().map(QPointF(0,0));
+ QPointF currentOffset = d->document->documentLayout()->blockBoundingRect(d->document->findBlock(firstCleanNode->startPos())).topLeft();
+ QPointF delta = currentOffset - oldOffset;
+ while (nodeIterator != d->textNodeMap.end()) {
+ QMatrix4x4 transformMatrix = (*nodeIterator)->textNode()->matrix();
+ transformMatrix.translate(delta.x(), delta.y());
+ (*nodeIterator)->textNode()->setMatrix(transformMatrix);
+ ++nodeIterator;
+ }
- node->addTextDocument(QPointF(d->xoff, d->yoff), d->document, d->color, QQuickText::Normal, QColor(),
- QColor(), d->selectionColor, d->selectedTextColor, selectionStart(),
- selectionEnd() - 1); // selectionEnd() returns first char after
- // selection
+ }
}
if (d->cursorComponent == 0 && !isReadOnly()) {
- QQuickTextNode *node = static_cast<QQuickTextNode *>(currentNode);
-
QColor color = (!d->cursorVisible || !d->control->cursorOn())
? QColor(0, 0, 0, 0)
: d->color;
-
- if (node->cursorNode() == 0) {
- node->setCursor(cursorRectangle(), color);
- } else {
- node->cursorNode()->setRect(cursorRectangle());
- node->cursorNode()->setColor(color);
- }
-
+ if (d->cursorNode)
+ rootNode->removeChildNode(d->cursorNode);
+ delete d->cursorNode;
+ d->cursorNode = new QSGSimpleRectNode(cursorRectangle(), color);
+ rootNode->appendChildNode(d->cursorNode);
}
- return currentNode;
+ return rootNode;
}
/*!
@@ -1789,27 +1936,28 @@ void QQuickTextEditPrivate::init()
control->setAcceptRichText(false);
control->setCursorIsFocusIndicator(true);
- qmlobject_connect(control, QQuickTextControl, SIGNAL(updateRequest()), q, QQuickTextEdit, SLOT(updateDocument()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(updateCursorRequest()), q, QQuickTextEdit, SLOT(updateCursor()));
- qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SIGNAL(selectedTextChanged()));
- qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SLOT(updateSelectionMarkers()));
- qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SLOT(updateSelectionMarkers()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SLOT(updateSelection()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SLOT(updateSelection()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SIGNAL(cursorPositionChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString)));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
#ifndef QT_NO_CLIPBOARD
qmlobject_connect(QGuiApplication::clipboard(), QClipboard, SIGNAL(dataChanged()), q, QQuickTextEdit, SLOT(q_canPasteChanged()));
#endif
qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(undoAvailable(bool)), q, QQuickTextEdit, SIGNAL(canUndoChanged()));
qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(redoAvailable(bool)), q, QQuickTextEdit, SIGNAL(canRedoChanged()));
qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(imagesLoaded()), q, QQuickTextEdit, SLOT(updateSize()));
+ QObject::connect(document, &QQuickTextDocumentWithImageResources::contentsChange, q, &QQuickTextEdit::q_contentsChange);
document->setDefaultFont(font);
document->setDocumentMargin(textMargin);
document->setUndoRedoEnabled(false); // flush undo buffer.
document->setUndoRedoEnabled(true);
updateDefaultTextOption();
+ q->updateSize();
}
void QQuickTextEdit::q_textChanged()
@@ -1828,6 +1976,44 @@ void QQuickTextEdit::q_textChanged()
emit textChanged();
}
+void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta)
+{
+ Q_D(QQuickTextEdit);
+ if (start == end)
+ return;
+ TextNode dummyNode(start, 0);
+ TextNodeIterator it = qLowerBound(d->textNodeMap.begin(), d->textNodeMap.end(), &dummyNode, &comesBefore);
+ // qLowerBound gives us the first node past the start of the affected portion, rewind by one if we can.
+ if (it != d->textNodeMap.begin())
+ --it;
+
+ // mark the affected nodes as dirty
+ while (it != d->textNodeMap.constEnd()) {
+ if ((*it)->startPos() <= end)
+ (*it)->setDirty();
+ else if (charDelta)
+ (*it)->moveStartPos(charDelta);
+ else
+ return;
+ ++it;
+ }
+}
+
+void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded)
+{
+ Q_D(QQuickTextEdit);
+
+ const int editRange = pos + qMax(charsAdded, charsRemoved);
+ const int delta = charsAdded - charsRemoved;
+
+ markDirtyNodesForRange(pos, editRange, delta);
+
+ if (isComponentComplete()) {
+ d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
+ update();
+ }
+}
+
void QQuickTextEdit::moveCursorDelegate()
{
Q_D(QQuickTextEdit);
@@ -1842,9 +2028,21 @@ void QQuickTextEdit::moveCursorDelegate()
d->cursorItem->setY(cursorRect.y());
}
-void QQuickTextEdit::updateSelectionMarkers()
+void QQuickTextEdit::updateSelection()
{
Q_D(QQuickTextEdit);
+
+ // No need for node updates when we go from an empty selection to another empty selection
+ if (d->control->textCursor().hasSelection() || d->hadSelection) {
+ markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0);
+ if (isComponentComplete()) {
+ d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
+ update();
+ }
+ }
+
+ d->hadSelection = d->control->textCursor().hasSelection();
+
if (d->lastSelectionStart != d->control->textCursor().selectionStart()) {
d->lastSelectionStart = d->control->textCursor().selectionStart();
emit selectionStartChanged();
@@ -1909,70 +2107,70 @@ qreal QQuickTextEditPrivate::getImplicitWidth() const
void QQuickTextEdit::updateSize()
{
Q_D(QQuickTextEdit);
- if (isComponentComplete()) {
- qreal naturalWidth = d->implicitWidth;
- // ### assumes that if the width is set, the text will fill to edges
- // ### (unless wrap is false, then clipping will occur)
- if (widthValid()) {
- if (!d->requireImplicitWidth) {
- emit implicitWidthChanged();
- // if the implicitWidth is used, then updateSize() has already been called (recursively)
- if (d->requireImplicitWidth)
- return;
- }
- if (d->requireImplicitWidth) {
- d->document->setTextWidth(-1);
- naturalWidth = d->document->idealWidth();
-
- const bool wasInLayout = d->inLayout;
- d->inLayout = true;
- setImplicitWidth(naturalWidth);
- d->inLayout = wasInLayout;
- if (d->inLayout) // probably the result of a binding loop, but by letting it
- return; // get this far we'll get a warning to that effect.
- }
- if (d->document->textWidth() != width())
- d->document->setTextWidth(width());
- } else {
+ if (!isComponentComplete()) {
+ d->dirty = true;
+ return;
+ }
+
+ qreal naturalWidth = d->implicitWidth;
+
+ qreal newWidth = d->document->idealWidth();
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid()) {
+ if (!d->requireImplicitWidth) {
+ emit implicitWidthChanged();
+ // if the implicitWidth is used, then updateSize() has already been called (recursively)
+ if (d->requireImplicitWidth)
+ return;
+ }
+ if (d->requireImplicitWidth) {
d->document->setTextWidth(-1);
+ naturalWidth = d->document->idealWidth();
+
+ const bool wasInLayout = d->inLayout;
+ d->inLayout = true;
+ setImplicitWidth(naturalWidth);
+ d->inLayout = wasInLayout;
+ if (d->inLayout) // probably the result of a binding loop, but by letting it
+ return; // get this far we'll get a warning to that effect.
}
-
+ if (d->document->textWidth() != width())
+ d->document->setTextWidth(width());
//### need to confirm cost of always setting these
- qreal newWidth = d->document->idealWidth();
- if ((!widthValid() || d->wrapMode == NoWrap) && d->document->textWidth() != newWidth)
- d->document->setTextWidth(newWidth); // ### Text does not align if width is not set or the idealWidth exceeds the textWidth (QTextDoc bug)
- // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
- qreal iWidth = -1;
- if (!widthValid() && !d->requireImplicitWidth)
- iWidth = newWidth;
-
- QFontMetricsF fm(d->font);
- qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height();
-
- if (iWidth > -1)
- setImplicitSize(iWidth, newHeight);
- else
- setImplicitHeight(newHeight);
+ } else if (d->wrapMode == NoWrap && d->document->textWidth() != newWidth) {
+ d->document->setTextWidth(newWidth); // ### Text does not align if width is not set or the idealWidth exceeds the textWidth (QTextDoc bug)
+ } else {
+ d->document->setTextWidth(-1);
+ }
- d->xoff = QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign());
- d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign);
- setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
+ QFontMetricsF fm(d->font);
+ qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height();
- QSizeF size(newWidth, newHeight);
- if (d->contentSize != size) {
- d->contentSize = size;
- emit contentSizeChanged();
- }
- } else {
- d->dirty = true;
+ // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
+ if (!widthValid() && !d->requireImplicitWidth)
+ setImplicitSize(newWidth, newHeight);
+ else
+ setImplicitHeight(newHeight);
+
+ d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign()));
+ d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign);
+ setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
+
+ QSizeF size(newWidth, newHeight);
+ if (d->contentSize != size) {
+ d->contentSize = size;
+ emit contentSizeChanged();
}
- updateDocument();
}
-void QQuickTextEdit::updateDocument()
+void QQuickTextEdit::updateWholeDocument()
{
Q_D(QQuickTextEdit);
- d->documentDirty = true;
+ if (!d->textNodeMap.isEmpty()) {
+ Q_FOREACH (TextNode* node, d->textNodeMap)
+ node->setDirty();
+ }
if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
@@ -1994,7 +2192,7 @@ void QQuickTextEdit::q_updateAlignment()
Q_D(QQuickTextEdit);
if (d->determineHorizontalAlignment()) {
d->updateDefaultTextOption();
- d->xoff = QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign());
+ d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign()));
moveCursorDelegate();
}
}
@@ -2062,12 +2260,36 @@ void QQuickTextEditPrivate::updateDefaultTextOption()
void QQuickTextEdit::focusInEvent(QFocusEvent *event)
{
- Q_D(const QQuickTextEdit);
+ Q_D(QQuickTextEdit);
+ d->handleFocusEvent(event);
+ QQuickImplicitSizeItem::focusInEvent(event);
+}
+
+void QQuickTextEdit::focusOutEvent(QFocusEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->handleFocusEvent(event);
+ QQuickImplicitSizeItem::focusOutEvent(event);
+}
+
+void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event)
+{
+ Q_Q(QQuickTextEdit);
+ bool focus = event->type() == QEvent::FocusIn;
+ q->setCursorVisible(focus);
+ control->processEvent(event, QPointF(-xoff, -yoff));
+ if (focus) {
+ q->q_updateAlignment();
#ifndef QT_NO_IM
- if (d->focusOnPress && !isReadOnly())
- qGuiApp->inputMethod()->show();
+ if (focusOnPress && !q->isReadOnly())
+ qGuiApp->inputMethod()->show();
+ q->connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
+ q, SLOT(q_updateAlignment()));
+ } else {
+ q->disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
+ q, SLOT(q_updateAlignment()));
#endif
- QQuickImplicitSizeItem::focusInEvent(event);
+ }
}
void QQuickTextEdit::q_canPasteChanged()
@@ -2179,4 +2401,23 @@ void QQuickTextEdit::remove(int start, int end)
d->control->updateCursorRectangle(false);
}
+/*!
+ \qmlproperty TextDocument QtQuick2::TextEdit::textDocument
+ \since QtQuick 2.1
+
+ Returns the QQuickTextDocument of this TextEdit.
+ It can be used to implement syntax highlighting using
+ \l QSyntaxHighlighter.
+
+ \sa QQuickTextDocument
+*/
+
+QQuickTextDocument *QQuickTextEdit::textDocument()
+{
+ Q_D(QQuickTextEdit);
+ if (!d->quickDocument)
+ d->quickDocument = new QQuickTextDocument(this);
+ return d->quickDocument;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index e88ca16c0e..4e09eafcac 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -46,10 +46,9 @@
#include <QtGui/qtextoption.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
+class QQuickTextDocument;
class QQuickTextEditPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
{
@@ -91,6 +90,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
#ifndef QT_NO_IM
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged)
#endif
+ Q_PROPERTY(bool selectByKeyboard READ selectByKeyboard WRITE setSelectByKeyboard NOTIFY selectByKeyboardChanged REVISION 1)
Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
@@ -101,6 +101,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
#endif
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
+ Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1)
public:
QQuickTextEdit(QQuickItem *parent=0);
@@ -201,6 +202,9 @@ public:
void setInputMethodHints(Qt::InputMethodHints hints);
#endif
+ bool selectByKeyboard() const;
+ void setSelectByKeyboard(bool);
+
bool selectByMouse() const;
void setSelectByMouse(bool);
@@ -249,6 +253,8 @@ public:
Q_INVOKABLE QString getText(int start, int end) const;
Q_INVOKABLE QString getFormattedText(int start, int end) const;
+ QQuickTextDocument *textDocument();
+
Q_SIGNALS:
void textChanged();
void contentSizeChanged();
@@ -272,6 +278,7 @@ Q_SIGNALS:
void activeFocusOnPressChanged(bool activeFocusOnPressed);
void persistentSelectionChanged(bool isPersistentSelection);
void textMarginChanged(qreal textMargin);
+ Q_REVISION(1) void selectByKeyboardChanged(bool selectByKeyboard);
void selectByMouseChanged(bool selectByMouse);
void mouseSelectionModeChanged(SelectionMode mode);
void linkActivated(const QString &link);
@@ -306,17 +313,19 @@ public Q_SLOTS:
private Q_SLOTS:
void q_textChanged();
- void updateSelectionMarkers();
+ void q_contentsChange(int, int, int);
+ void updateSelection();
void moveCursorDelegate();
void createCursor();
void q_canPasteChanged();
- void updateDocument();
+ void updateWholeDocument();
void updateCursor();
void q_updateAlignment();
void updateSize();
void triggerPreprocess();
private:
+ void markDirtyNodesForRange(int start, int end, int charDelta);
void updateTotalLines();
protected:
@@ -327,6 +336,7 @@ protected:
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
void focusInEvent(QFocusEvent *event);
+ void focusOutEvent(QFocusEvent *event);
// mouse filter?
void mousePressEvent(QMouseEvent *event);
@@ -336,11 +346,10 @@ protected:
#ifndef QT_NO_IM
void inputMethodEvent(QInputMethodEvent *e);
#endif
- virtual void itemChange(ItemChange, const ItemChangeData &);
-
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
friend class QQuickTextUtil;
+ friend class QQuickTextDocument;
private:
Q_DISABLE_COPY(QQuickTextEdit)
@@ -351,6 +360,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTextEdit)
-QT_END_HEADER
-
#endif // QQUICKTEXTEDIT_P_H
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 597874d864..feb7e98873 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -58,11 +58,14 @@
#include "qquicktextcontrol_p.h"
#include <QtQml/qqml.h>
+#include <QtCore/qlist.h>
QT_BEGIN_NAMESPACE
class QTextLayout;
class QQuickTextDocumentWithImageResources;
class QQuickTextControl;
+class QQuickTextNode;
+class QSGSimpleRectNode;
class QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate
{
public:
@@ -70,9 +73,26 @@ public:
typedef QQuickTextEdit Public;
+ struct Node {
+ explicit Node(int startPos, QQuickTextNode* node)
+ : m_startPos(startPos), m_node(node), m_dirty(false) { }
+ QQuickTextNode* textNode() const { return m_node; }
+ void moveStartPos(int delta) { Q_ASSERT(m_startPos + delta > 0); m_startPos += delta; }
+ int startPos() const { return m_startPos; }
+ void setDirty() { m_dirty = true; }
+ bool dirty() const { return m_dirty; }
+
+ private:
+ int m_startPos;
+ QQuickTextNode* m_node;
+ bool m_dirty;
+ };
+
+
QQuickTextEditPrivate()
: color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF))
, textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
+ , quickDocument(0), frameDecorationsNode(0), cursorNode(0)
, lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
, hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
, format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
@@ -83,10 +103,11 @@ public:
, inputMethodHints(Qt::ImhNone)
#endif
, updateType(UpdatePaintNode)
- , documentDirty(true), dirty(false), richText(false), cursorVisible(false), cursorPending(false)
+ , dirty(false), richText(false), cursorVisible(false), cursorPending(false)
, focusOnPress(true), persistentSelection(false), requireImplicitWidth(false)
, selectByMouse(false), canPaste(false), canPasteValid(false), hAlignImplicit(true)
- , textCached(true), inLayout(false)
+ , textCached(true), inLayout(false), selectByKeyboard(false), selectByKeyboardSet(false)
+ , hadSelection(false)
{
}
@@ -104,6 +125,11 @@ public:
Qt::LayoutDirection textDirection(const QString &text) const;
void setNativeCursorEnabled(bool enabled) { control->setCursorWidth(enabled ? 1 : 0); }
+ void handleFocusEvent(QFocusEvent *event);
+
+#ifndef QT_NO_IM
+ Qt::InputMethodHints effectiveInputMethodHints() const;
+#endif
QColor color;
QColor selectionColor;
@@ -124,6 +150,10 @@ public:
QQuickItem* cursorItem;
QQuickTextDocumentWithImageResources *document;
QQuickTextControl *control;
+ QQuickTextDocument *quickDocument;
+ QList<Node*> textNodeMap;
+ QQuickTextNode *frameDecorationsNode;
+ QSGSimpleRectNode *cursorNode;
int lastSelectionStart;
int lastSelectionEnd;
@@ -147,7 +177,6 @@ public:
#endif
UpdateType updateType;
- bool documentDirty : 1;
bool dirty : 1;
bool richText : 1;
bool cursorVisible : 1;
@@ -161,6 +190,9 @@ public:
bool hAlignImplicit:1;
bool textCached:1;
bool inLayout:1;
+ bool selectByKeyboard:1;
+ bool selectByKeyboardSet:1;
+ bool hadSelection : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index f9de3d25e7..52f991b475 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -153,6 +153,8 @@ void QQuickTextInput::setText(const QString &s)
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
+
+ On HighDpi "retina" displays this property is ignored and QtRendering is always used.
*/
QQuickTextInput::RenderType QQuickTextInput::renderType() const
{
@@ -1836,7 +1838,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
}
}
} else {
- node->setUseNativeRenderer(d->renderType == QQuickTextInput::NativeRendering);
+ node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
node->deleteContent();
node->setMatrix(QMatrix4x4());
@@ -1910,7 +1912,7 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
else
return QVariant(d->selectionStart());
default:
- return QVariant();
+ return QQuickItem::inputMethodQuery(property);
}
}
#endif // QT_NO_IM
@@ -2477,40 +2479,47 @@ void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
void QQuickTextInput::focusInEvent(QFocusEvent *event)
{
- Q_D(const QQuickTextInput);
-#ifndef QT_NO_IM
- if (d->focusOnPress && !d->m_readOnly)
- qGuiApp->inputMethod()->show();
-#endif
+ Q_D(QQuickTextInput);
+ d->handleFocusEvent(event);
QQuickImplicitSizeItem::focusInEvent(event);
}
-void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
+void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event)
{
- Q_D(QQuickTextInput);
- if (change == ItemActiveFocusHasChanged) {
- bool hasFocus = value.boolValue;
- setCursorVisible(hasFocus);
- if (!hasFocus && (d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive())) {
- d->updatePasswordEchoEditing(false);//QQuickTextInputPrivate sets it on key events, but doesn't deal with focus events
- }
-
- if (!hasFocus) {
- if (!d->persistentSelection)
- d->deselect();
+ Q_Q(QQuickTextInput);
+ bool focus = event->gotFocus();
+ q->setCursorVisible(focus);
+ if (focus) {
+ q->q_updateAlignment();
#ifndef QT_NO_IM
- disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
- this, SLOT(q_updateAlignment()));
+ if (focusOnPress && !m_readOnly)
+ qGuiApp->inputMethod()->show();
+ q->connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
+ q, SLOT(q_updateAlignment()));
#endif
- } else {
- q_updateAlignment();
+ } else {
+ if ((m_passwordEchoEditing || m_passwordEchoTimer.isActive())) {
+ updatePasswordEchoEditing(false);//QQuickTextInputPrivate sets it on key events, but doesn't deal with focus events
+ }
+
+ if (event->reason() != Qt::ActiveWindowFocusReason
+ && event->reason() != Qt::PopupFocusReason
+ && hasSelectedText()
+ && !persistentSelection)
+ deselect();
+
#ifndef QT_NO_IM
- connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
- this, SLOT(q_updateAlignment()));
+ q->disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
+ q, SLOT(q_updateAlignment()));
#endif
- }
}
- QQuickItem::itemChange(change, value);
+}
+
+void QQuickTextInput::focusOutEvent(QFocusEvent *event)
+{
+ Q_D(QQuickTextInput);
+ d->handleFocusEvent(event);
+ QQuickImplicitSizeItem::focusOutEvent(event);
}
#ifndef QT_NO_IM
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 83bc125dee..e66d9b4964 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -46,8 +46,6 @@
#include <QtGui/qtextoption.h>
#include <QtGui/qvalidator.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickTextInputPrivate;
@@ -334,9 +332,9 @@ protected:
#endif
void mouseUngrabEvent();
bool event(QEvent *e);
+ void focusOutEvent(QFocusEvent *event);
void focusInEvent(QFocusEvent *event);
void timerEvent(QTimerEvent *event);
- virtual void itemChange(ItemChange, const ItemChangeData &);
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
public Q_SLOTS:
@@ -415,6 +413,4 @@ QML_DECLARE_TYPE(QQuickDoubleValidator)
QML_DECLARE_TYPE(QRegExpValidator)
#endif
-QT_END_HEADER
-
#endif // QQUICKTEXTINPUT_P_H
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 2b3809799b..57eff175a2 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -158,7 +158,7 @@ public:
#endif
void hideCursor();
void showCursor();
-
+ void handleFocusEvent(QFocusEvent *event);
struct MaskInputData {
enum Casemode { NoCaseMode, Upper, Lower };
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 5e1b20c032..d46959464a 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -41,6 +41,8 @@
#include "qquicktextnode_p.h"
+#include "qquicktextnodeengine_p.h"
+
#include <QtQuick/qsgsimplerectnode.h>
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgdistancefieldglyphnode_p.h>
@@ -53,20 +55,28 @@
#include <qtextlayout.h>
#include <qabstracttextdocumentlayout.h>
#include <qxmlstream.h>
-#include <qrawfont.h>
-#include <qtexttable.h>
-#include <qtextlist.h>
#include <private/qquickstyledtext_p.h>
-#include <private/qquicktext_p_p.h>
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
-#include <private/qrawfont_p.h>
-#include <private/qtextimagehandler_p.h>
+
#include <private/qtextdocumentlayout_p.h>
#include <qhash.h>
QT_BEGIN_NAMESPACE
+namespace {
+
+ class ProtectedLayoutAccessor: public QAbstractTextDocumentLayout
+ {
+ public:
+ inline QTextCharFormat formatAccessor(int pos)
+ {
+ return format(pos);
+ }
+ };
+
+}
+
/*!
Creates an empty QQuickTextNode
*/
@@ -166,937 +176,14 @@ void QQuickTextNode::setCursor(const QRectF &rect, const QColor &color)
appendChildNode(m_cursorNode);
}
-namespace {
-
- struct BinaryTreeNode {
- enum SelectionState {
- Unselected,
- Selected
- };
-
- BinaryTreeNode()
- : selectionState(Unselected)
- , clipNode(0)
- , decorations(QQuickTextNode::NoDecoration)
- , ascent(0.0)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
-
- }
-
- BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a)
- : boundingRect(brect)
- , selectionState(selState)
- , clipNode(0)
- , decorations(QQuickTextNode::NoDecoration)
- , image(i)
- , ascent(a)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
- }
-
- BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
- const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc,
- const QPointF &pos, qreal a)
- : glyphRun(g)
- , boundingRect(brect)
- , selectionState(selState)
- , clipNode(0)
- , decorations(decs)
- , color(c)
- , backgroundColor(bc)
- , position(pos)
- , ascent(a)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
- }
-
- QGlyphRun glyphRun;
- QRectF boundingRect;
- SelectionState selectionState;
- QQuickDefaultClipNode *clipNode;
- QQuickTextNode::Decorations decorations;
- QColor color;
- QColor backgroundColor;
- QPointF position;
- QImage image;
- qreal ascent;
-
- int leftChildIndex;
- int rightChildIndex;
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const QRectF &rect,
- const QImage &image,
- qreal ascent,
- SelectionState selectionState)
- {
- insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent));
- }
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const QGlyphRun &glyphRun,
- SelectionState selectionState,
- QQuickTextNode::Decorations decorations,
- const QColor &textColor,
- const QColor &backgroundColor,
- const QPointF &position)
- {
- QRectF searchRect = glyphRun.boundingRect();
- searchRect.translate(position);
-
- if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
- return;
-
- decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration);
- decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration);
- decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration);
- decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
-
- qreal ascent = glyphRun.rawFont().ascent();
- insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
- textColor, backgroundColor, position, ascent));
- }
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const BinaryTreeNode &binaryTreeNode)
- {
- int newIndex = binaryTree->size();
- binaryTree->append(binaryTreeNode);
- if (newIndex == 0)
- return;
-
- int searchIndex = 0;
- forever {
- BinaryTreeNode *node = binaryTree->data() + searchIndex;
- if (binaryTreeNode.boundingRect.left() < node->boundingRect.left()) {
- if (node->leftChildIndex < 0) {
- node->leftChildIndex = newIndex;
- break;
- } else {
- searchIndex = node->leftChildIndex;
- }
- } else {
- if (node->rightChildIndex < 0) {
- node->rightChildIndex = newIndex;
- break;
- } else {
- searchIndex = node->rightChildIndex;
- }
- }
- }
- }
-
- static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
- QVarLengthArray<int> *sortedIndexes,
- int currentIndex = 0)
- {
- Q_ASSERT(currentIndex < binaryTree.size());
-
- const BinaryTreeNode *node = binaryTree.data() + currentIndex;
- if (node->leftChildIndex >= 0)
- inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
-
- sortedIndexes->append(currentIndex);
-
- if (node->rightChildIndex >= 0)
- inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
- }
- };
-
- // Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
- // and rectangle nodes to represent the text, decorations and selection. Will try to minimize
- // number of nodes, and join decorations in neighbouring items
- class SelectionEngine
- {
- public:
- SelectionEngine() : m_hasSelection(false) {}
-
- QTextLine currentLine() const { return m_currentLine; }
-
- void setCurrentLine(const QTextLine &currentLine)
- {
- if (m_currentLine.isValid())
- processCurrentLine();
-
- m_currentLine = currentLine;
- }
-
- void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle,
- const QBrush &borderBrush);
- void addFrameDecorations(QTextDocument *document, QTextFrame *frame);
- void addImage(const QRectF &rect, const QImage &image, qreal ascent,
- BinaryTreeNode::SelectionState selectionState,
- QTextFrameFormat::Position layoutPosition);
- int addText(const QTextBlock &block,
- const QTextCharFormat &charFormat,
- const QColor &textColor,
- const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
- int textPos, int fragmentEnd,
- int selectionStart, int selectionEnd);
- void addTextObject(const QPointF &position, const QTextCharFormat &format,
- BinaryTreeNode::SelectionState selectionState,
- QTextDocument *textDocument, int pos,
- QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
- void addSelectedGlyphs(const QGlyphRun &glyphRun);
- void addUnselectedGlyphs(const QGlyphRun &glyphRun);
- void addGlyphsInRange(int rangeStart, int rangeEnd,
- const QColor &color, const QColor &backgroundColor,
- int selectionStart, int selectionEnd);
- void addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
- int start, int end,
- int selectionStart, int selectionEnd);
-
- void addToSceneGraph(QQuickTextNode *parent,
- QQuickText::TextStyle style = QQuickText::Normal,
- const QColor &styleColor = QColor());
-
- void setSelectionColor(const QColor &selectionColor)
- {
- m_selectionColor = selectionColor;
- }
-
- void setSelectedTextColor(const QColor &selectedTextColor)
- {
- m_selectedTextColor = selectedTextColor;
- }
-
- void setTextColor(const QColor &textColor)
- {
- m_textColor = textColor;
- }
-
- void setAnchorColor(const QColor &anchorColor)
- {
- m_anchorColor = anchorColor;
- }
-
- void setPosition(const QPointF &position)
- {
- m_position = position;
- }
-
- private:
- struct TextDecoration
- {
- TextDecoration() : selectionState(BinaryTreeNode::Unselected) {}
- TextDecoration(const BinaryTreeNode::SelectionState &s,
- const QRectF &r,
- const QColor &c)
- : selectionState(s)
- , rect(r)
- , color(c)
- {
- }
-
- BinaryTreeNode::SelectionState selectionState;
- QRectF rect;
- QColor color;
- };
-
- void processCurrentLine();
- void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
- qreal offset, qreal thickness);
-
- QColor m_selectionColor;
- QColor m_textColor;
- QColor m_backgroundColor;
- QColor m_selectedTextColor;
- QColor m_anchorColor;
- QPointF m_position;
-
- QTextLine m_currentLine;
- bool m_hasSelection;
-
- QList<QPair<QRectF, QColor> > m_backgrounds;
- QList<QRectF> m_selectionRects;
- QVarLengthArray<BinaryTreeNode> m_currentLineTree;
-
- QList<TextDecoration> m_lines;
- QVector<BinaryTreeNode> m_processedNodes;
-
- QList<QPair<QRectF, QImage> > m_images;
- };
-
- int SelectionEngine::addText(const QTextBlock &block,
- const QTextCharFormat &charFormat,
- const QColor &textColor,
- const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
- int textPos, int fragmentEnd,
- int selectionStart, int selectionEnd)
- {
- if (charFormat.foreground().style() != Qt::NoBrush)
- setTextColor(charFormat.foreground().color());
- else
- setTextColor(textColor);
-
- while (textPos < fragmentEnd) {
- int blockRelativePosition = textPos - block.position();
- QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
- if (!currentLine().isValid()
- || line.lineNumber() != currentLine().lineNumber()) {
- setCurrentLine(line);
- }
-
- Q_ASSERT(line.textLength() > 0);
- int lineEnd = line.textStart() + block.position() + line.textLength();
-
- int len = qMin(lineEnd - textPos, fragmentEnd - textPos);
- Q_ASSERT(len > 0);
-
- int currentStepEnd = textPos + len;
-
- addGlyphsForRanges(colorChanges,
- textPos - block.position(),
- currentStepEnd - block.position(),
- selectionStart - block.position(),
- selectionEnd - block.position());
-
- textPos = currentStepEnd;
- }
- return textPos;
- }
-
- void SelectionEngine::addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
- qreal offset, qreal thickness)
- {
- for (int i=0; i<textDecorations.size(); ++i) {
- TextDecoration textDecoration = textDecorations.at(i);
-
- {
- QRectF &rect = textDecoration.rect;
- rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
- rect.setHeight(thickness);
- }
-
- m_lines.append(textDecoration);
- }
- }
-
- void SelectionEngine::processCurrentLine()
- {
- // No glyphs, do nothing
- if (m_currentLineTree.isEmpty())
- return;
-
- // 1. Go through current line and get correct decoration position for each node based on
- // neighbouring decorations. Add decoration to global list
- // 2. Create clip nodes for all selected text. Try to merge as many as possible within
- // the line.
- // 3. Add QRects to a list of selection rects.
- // 4. Add all nodes to a global processed list
- QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
- BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);
-
- Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());
-
- BinaryTreeNode::SelectionState currentSelectionState = BinaryTreeNode::Unselected;
- QRectF currentRect;
-
- QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
- qreal underlineOffset = 0.0;
- qreal underlineThickness = 0.0;
-
- qreal overlineOffset = 0.0;
- qreal overlineThickness = 0.0;
-
- qreal strikeOutOffset = 0.0;
- qreal strikeOutThickness = 0.0;
-
- QRectF decorationRect = currentRect;
-
- QColor lastColor;
- QColor lastBackgroundColor;
-
- QVarLengthArray<TextDecoration> pendingUnderlines;
- QVarLengthArray<TextDecoration> pendingOverlines;
- QVarLengthArray<TextDecoration> pendingStrikeOuts;
- if (!sortedIndexes.isEmpty()) {
- QQuickDefaultClipNode *currentClipNode = m_hasSelection ? new QQuickDefaultClipNode(QRectF()) : 0;
- bool currentClipNodeUsed = false;
- for (int i=0; i<=sortedIndexes.size(); ++i) {
- BinaryTreeNode *node = 0;
- if (i < sortedIndexes.size()) {
- int sortedIndex = sortedIndexes.at(i);
- Q_ASSERT(sortedIndex < m_currentLineTree.size());
-
- node = m_currentLineTree.data() + sortedIndex;
- }
-
- if (i == 0)
- currentSelectionState = node->selectionState;
-
- // Update decorations
- if (currentDecorations != QQuickTextNode::NoDecoration) {
- decorationRect.setY(m_position.y() + m_currentLine.y());
- decorationRect.setHeight(m_currentLine.height());
-
- if (node != 0)
- decorationRect.setRight(node->boundingRect.left());
-
- TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
- if (currentDecorations & QQuickTextNode::Underline)
- pendingUnderlines.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::Overline)
- pendingOverlines.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::StrikeOut)
- pendingStrikeOuts.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::Background)
- m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
- }
-
- // If we've reached an unselected node from a selected node, we add the
- // selection rect to the graph, and we add decoration every time the
- // selection state changes, because that means the text color changes
- if (node == 0 || node->selectionState != currentSelectionState) {
- if (node != 0)
- currentRect.setRight(node->boundingRect.left());
- currentRect.setY(m_position.y() + m_currentLine.y());
- currentRect.setHeight(m_currentLine.height());
-
- // Draw selection all the way up to the left edge of the unselected item
- if (currentSelectionState == BinaryTreeNode::Selected)
- m_selectionRects.append(currentRect);
-
- if (currentClipNode != 0) {
- if (!currentClipNodeUsed) {
- delete currentClipNode;
- } else {
- currentClipNode->setIsRectangular(true);
- currentClipNode->setRect(currentRect);
- currentClipNode->update();
- }
- }
-
- if (node != 0 && m_hasSelection)
- currentClipNode = new QQuickDefaultClipNode(QRectF());
- else
- currentClipNode = 0;
- currentClipNodeUsed = false;
-
- if (node != 0) {
- currentSelectionState = node->selectionState;
- currentRect = node->boundingRect;
-
- // Make sure currentRect is valid, otherwise the unite won't work
- if (currentRect.isNull())
- currentRect.setSize(QSizeF(1, 1));
- }
- } else {
- if (currentRect.isNull())
- currentRect = node->boundingRect;
- else
- currentRect = currentRect.united(node->boundingRect);
- }
-
- if (node != 0) {
- node->clipNode = currentClipNode;
- currentClipNodeUsed = true;
-
- decorationRect = node->boundingRect;
-
- // If previous item(s) had underline and current does not, then we add the
- // pending lines to the lists and likewise for overlines and strikeouts
- if (!pendingUnderlines.isEmpty()
- && !(node->decorations & QQuickTextNode::Underline)) {
- addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
-
- pendingUnderlines.clear();
-
- underlineOffset = 0.0;
- underlineThickness = 0.0;
- }
-
- // ### Add pending when overlineOffset/thickness changes to minimize number of
- // nodes
- if (!pendingOverlines.isEmpty()) {
- addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
-
- pendingOverlines.clear();
-
- overlineOffset = 0.0;
- overlineThickness = 0.0;
- }
-
- // ### Add pending when overlineOffset/thickness changes to minimize number of
- // nodes
- if (!pendingStrikeOuts.isEmpty()) {
- addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
-
- pendingStrikeOuts.clear();
-
- strikeOutOffset = 0.0;
- strikeOutThickness = 0.0;
- }
-
- // Merge current values with previous. Prefer greatest thickness
- QRawFont rawFont = node->glyphRun.rawFont();
- if (node->decorations & QQuickTextNode::Underline) {
- if (rawFont.lineThickness() > underlineThickness) {
- underlineThickness = rawFont.lineThickness();
- underlineOffset = rawFont.underlinePosition();
- }
- }
-
- if (node->decorations & QQuickTextNode::Overline) {
- overlineOffset = -rawFont.ascent();
- overlineThickness = rawFont.lineThickness();
- }
-
- if (node->decorations & QQuickTextNode::StrikeOut) {
- strikeOutThickness = rawFont.lineThickness();
- strikeOutOffset = rawFont.ascent() / -3.0;
- }
-
- currentDecorations = node->decorations;
- lastColor = node->color;
- lastBackgroundColor = node->backgroundColor;
- m_processedNodes.append(*node);
- }
- }
-
- if (!pendingUnderlines.isEmpty())
- addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
-
- if (!pendingOverlines.isEmpty())
- addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
-
- if (!pendingStrikeOuts.isEmpty())
- addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
- }
-
- m_currentLineTree.clear();
- m_currentLine = QTextLine();
- m_hasSelection = false;
- }
-
- void SelectionEngine::addImage(const QRectF &rect, const QImage &image, qreal ascent,
- BinaryTreeNode::SelectionState selectionState,
- QTextFrameFormat::Position layoutPosition)
- {
- QRectF searchRect = rect;
- if (layoutPosition == QTextFrameFormat::InFlow) {
- if (m_currentLineTree.isEmpty()) {
- searchRect.moveTopLeft(m_position + m_currentLine.position());
- } else {
- const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1;
- if (lastNode->glyphRun.isRightToLeft()) {
- QPointF lastPos = lastNode->boundingRect.topLeft();
- searchRect.moveTopRight(lastPos - QPointF(0, ascent - lastNode->ascent));
- } else {
- QPointF lastPos = lastNode->boundingRect.topRight();
- searchRect.moveTopLeft(lastPos - QPointF(0, ascent - lastNode->ascent));
- }
- }
- }
-
- BinaryTreeNode::insert(&m_currentLineTree, searchRect, image, ascent, selectionState);
- }
-
- void SelectionEngine::addTextObject(const QPointF &position, const QTextCharFormat &format,
- BinaryTreeNode::SelectionState selectionState,
- QTextDocument *textDocument, int pos,
- QTextFrameFormat::Position layoutPosition)
- {
- QTextObjectInterface *handler = textDocument->documentLayout()->handlerForObject(format.objectType());
- if (handler != 0) {
- QImage image;
- QSizeF size = handler->intrinsicSize(textDocument, pos, format);
-
- if (format.objectType() == QTextFormat::ImageObject) {
- QTextImageFormat imageFormat = format.toImageFormat();
- if (QQuickTextDocumentWithImageResources *imageDoc = qobject_cast<QQuickTextDocumentWithImageResources *>(textDocument)) {
- image = imageDoc->image(imageFormat);
-
- if (image.isNull())
- return;
- } else {
- QTextImageHandler *imageHandler = static_cast<QTextImageHandler *>(handler);
- image = imageHandler->image(textDocument, imageFormat);
- }
- }
-
- if (image.isNull()) {
- image = QImage(size.toSize(), QImage::Format_ARGB32_Premultiplied);
- image.fill(Qt::transparent);
- {
- QPainter painter(&image);
- handler->drawObject(&painter, image.rect(), textDocument, pos, format);
- }
- }
-
- qreal ascent;
- QFontMetrics m(format.font());
- switch (format.verticalAlignment())
- {
- case QTextCharFormat::AlignMiddle:
- ascent = size.height() / 2 - 1;
- break;
- case QTextCharFormat::AlignBaseline:
- ascent = size.height() - m.descent() - 1;
- break;
- default:
- ascent = size.height() - 1;
- }
-
- addImage(QRectF(position, size), image, ascent, selectionState, layoutPosition);
- }
- }
-
- void SelectionEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
- {
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Unselected,
- QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position);
- }
-
- void SelectionEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
- {
- int currentSize = m_currentLineTree.size();
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Selected,
- QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position);
- m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
- }
-
- void SelectionEngine::addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
- int start, int end,
- int selectionStart, int selectionEnd)
- {
- int currentPosition = start;
- int remainingLength = end - start;
- for (int j=0; j<ranges.size(); ++j) {
- const QTextLayout::FormatRange &range = ranges.at(j);
- if (range.start + range.length >= currentPosition
- && range.start < currentPosition + remainingLength) {
-
- if (range.start > currentPosition) {
- addGlyphsInRange(currentPosition, range.start - currentPosition,
- QColor(), QColor(), selectionStart, selectionEnd);
- }
- int rangeEnd = qMin(range.start + range.length, currentPosition + remainingLength);
- QColor rangeColor;
- if (range.format.hasProperty(QTextFormat::ForegroundBrush))
- rangeColor = range.format.foreground().color();
- else if (range.format.isAnchor())
- rangeColor = m_anchorColor;
- QColor rangeBackgroundColor = range.format.hasProperty(QTextFormat::BackgroundBrush)
- ? range.format.background().color()
- : QColor();
-
- addGlyphsInRange(range.start, rangeEnd - range.start,
- rangeColor, rangeBackgroundColor,
- selectionStart, selectionEnd);
-
- currentPosition = range.start + range.length;
- remainingLength = end - currentPosition;
-
- } else if (range.start > currentPosition + remainingLength || remainingLength <= 0) {
- break;
- }
- }
-
- if (remainingLength > 0) {
- addGlyphsInRange(currentPosition, remainingLength, QColor(), QColor(),
- selectionStart, selectionEnd);
- }
-
- }
-
- void SelectionEngine::addGlyphsInRange(int rangeStart, int rangeLength,
- const QColor &color, const QColor &backgroundColor,
- int selectionStart, int selectionEnd)
- {
- QColor oldColor;
- if (color.isValid()) {
- oldColor = m_textColor;
- m_textColor = color;
- }
-
- QColor oldBackgroundColor = m_backgroundColor;
- if (backgroundColor.isValid()) {
- oldBackgroundColor = m_backgroundColor;
- m_backgroundColor = backgroundColor;
- }
-
- bool hasSelection = selectionEnd >= 0
- && selectionStart <= selectionEnd;
-
- QTextLine &line = m_currentLine;
- int rangeEnd = rangeStart + rangeLength;
- if (!hasSelection || (selectionStart > rangeEnd || selectionEnd < rangeStart)) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- } else {
- if (rangeStart < selectionStart) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart,
- qMin(selectionStart - rangeStart,
- rangeLength));
-
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- }
-
- if (rangeEnd > selectionStart) {
- int start = qMax(selectionStart, rangeStart);
- int length = qMin(selectionEnd - start + 1, rangeEnd - start);
- QList<QGlyphRun> glyphRuns = line.glyphRuns(start, length);
-
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addSelectedGlyphs(glyphRun);
- }
- }
-
- if (selectionEnd >= rangeStart && selectionEnd < rangeEnd) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, rangeEnd - selectionEnd - 1);
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- }
- }
-
- if (backgroundColor.isValid())
- m_backgroundColor = oldBackgroundColor;
-
- if (oldColor.isValid())
- m_textColor = oldColor;
- }
-
- void SelectionEngine::addBorder(const QRectF &rect, qreal border,
- QTextFrameFormat::BorderStyle borderStyle,
- const QBrush &borderBrush)
- {
- QColor color = borderBrush.color();
-
- // Currently we don't support other styles than solid
- Q_UNUSED(borderStyle);
-
- m_backgrounds.append(qMakePair(QRectF(rect.left(), rect.top(), border, rect.height() + border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.top(), rect.width(), border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.right(), rect.top() + border, border, rect.height() - border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.bottom(), rect.width(), border), color));
- }
-
- void SelectionEngine::addFrameDecorations(QTextDocument *document, QTextFrame *frame)
- {
- QTextDocumentLayout *documentLayout = qobject_cast<QTextDocumentLayout *>(document->documentLayout());
- QTextFrameFormat frameFormat = frame->format().toFrameFormat();
-
- QTextTable *table = qobject_cast<QTextTable *>(frame);
- QRectF boundingRect = table == 0
- ? documentLayout->frameBoundingRect(frame)
- : documentLayout->tableBoundingRect(table);
-
- QBrush bg = frame->frameFormat().background();
- if (bg.style() != Qt::NoBrush)
- m_backgrounds.append(qMakePair(boundingRect, bg.color()));
-
- if (!frameFormat.hasProperty(QTextFormat::FrameBorder))
- return;
-
- qreal borderWidth = frameFormat.border();
- if (qFuzzyIsNull(borderWidth))
- return;
-
- QBrush borderBrush = frameFormat.borderBrush();
- QTextFrameFormat::BorderStyle borderStyle = frameFormat.borderStyle();
- if (borderStyle == QTextFrameFormat::BorderStyle_None)
- return;
-
- addBorder(boundingRect.adjusted(frameFormat.leftMargin(), frameFormat.topMargin(),
- -frameFormat.rightMargin(), -frameFormat.bottomMargin()),
- borderWidth, borderStyle, borderBrush);
- if (table != 0) {
- int rows = table->rows();
- int columns = table->columns();
-
- for (int row=0; row<rows; ++row) {
- for (int column=0; column<columns; ++column) {
- QTextTableCell cell = table->cellAt(row, column);
-
- QRectF cellRect = documentLayout->tableCellBoundingRect(table, cell);
- addBorder(cellRect.adjusted(-borderWidth, -borderWidth, 0, 0), borderWidth,
- borderStyle, borderBrush);
- }
- }
- }
- }
-
- void SelectionEngine::addToSceneGraph(QQuickTextNode *parentNode,
- QQuickText::TextStyle style,
- const QColor &styleColor)
- {
- if (m_currentLine.isValid())
- processCurrentLine();
-
-
- for (int i=0; i<m_backgrounds.size(); ++i) {
- const QRectF &rect = m_backgrounds.at(i).first;
- const QColor &color = m_backgrounds.at(i).second;
-
- parentNode->appendChildNode(new QSGSimpleRectNode(rect, color));
- }
-
- // First, prepend all selection rectangles to the tree
- for (int i=0; i<m_selectionRects.size(); ++i) {
- const QRectF &rect = m_selectionRects.at(i);
-
- parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
- }
-
- // Finally, add decorations for each node to the tree.
- for (int i=0; i<m_lines.size(); ++i) {
- const TextDecoration &textDecoration = m_lines.at(i);
-
- QColor color = textDecoration.selectionState == BinaryTreeNode::Selected
- ? m_selectedTextColor
- : textDecoration.color;
-
- parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
- }
-
- // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
- // font, selection state and clip node.
- typedef QPair<QFontEngine *, QPair<QQuickDefaultClipNode *, QPair<QRgb, int> > > KeyType;
- QHash<KeyType, BinaryTreeNode *> map;
- QList<BinaryTreeNode *> nodes;
- for (int i=0; i<m_processedNodes.size(); ++i) {
- BinaryTreeNode *node = m_processedNodes.data() + i;
-
- if (node->image.isNull()) {
- QGlyphRun glyphRun = node->glyphRun;
- QRawFont rawFont = glyphRun.rawFont();
- QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
-
- QFontEngine *fontEngine = rawFontD->fontEngine;
-
- KeyType key(qMakePair(fontEngine,
- qMakePair(node->clipNode,
- qMakePair(node->color.rgba(), int(node->selectionState)))));
-
- BinaryTreeNode *otherNode = map.value(key, 0);
- if (otherNode != 0) {
- QGlyphRun &otherGlyphRun = otherNode->glyphRun;
-
- QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
- QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();
-
- otherGlyphIndexes += glyphRun.glyphIndexes();
-
- QVector<QPointF> glyphPositions = glyphRun.positions();
- for (int j=0; j<glyphPositions.size(); ++j) {
- otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
- }
-
- otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
- otherGlyphRun.setPositions(otherGlyphPositions);
-
- } else {
- map.insert(key, node);
- nodes.append(node);
- }
- } else {
- parentNode->addImage(node->boundingRect, node->image);
- if (node->selectionState == BinaryTreeNode::Selected) {
- QColor color = m_selectionColor;
- color.setAlpha(128);
- parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color));
- }
- }
- }
-
- // ...and add clip nodes and glyphs to tree.
- foreach (const BinaryTreeNode *node, nodes) {
-
- QQuickDefaultClipNode *clipNode = node->clipNode;
- if (clipNode != 0 && clipNode->parent() == 0 )
- parentNode->appendChildNode(clipNode);
-
- QColor color = node->selectionState == BinaryTreeNode::Selected
- ? m_selectedTextColor
- : node->color;
-
- parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
- }
- }
-}
-
-void QQuickTextNode::mergeFormats(QTextLayout *textLayout,
- QVarLengthArray<QTextLayout::FormatRange> *mergedFormats)
+void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor, const QColor& anchorColor)
{
- Q_ASSERT(mergedFormats != 0);
- if (textLayout == 0)
- return;
-
- QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
- for (int i=0; i<additionalFormats.size(); ++i) {
- QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
- if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
- || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)
- || additionalFormat.format.isAnchor()) {
- // Merge overlapping formats
- if (!mergedFormats->isEmpty()) {
- QTextLayout::FormatRange *lastFormat = mergedFormats->data() + mergedFormats->size() - 1;
-
- if (additionalFormat.start < lastFormat->start + lastFormat->length) {
- QTextLayout::FormatRange *mergedRange = 0;
-
- int length = additionalFormat.length;
- if (additionalFormat.start > lastFormat->start) {
- lastFormat->length = additionalFormat.start - lastFormat->start;
- length -= lastFormat->length;
-
- mergedFormats->append(QTextLayout::FormatRange());
- mergedRange = mergedFormats->data() + mergedFormats->size() - 1;
- lastFormat = mergedFormats->data() + mergedFormats->size() - 2;
- } else {
- mergedRange = lastFormat;
- }
-
- mergedRange->format = lastFormat->format;
- mergedRange->format.merge(additionalFormat.format);
- mergedRange->start = additionalFormat.start;
-
- int end = qMin(additionalFormat.start + additionalFormat.length,
- lastFormat->start + lastFormat->length);
-
- mergedRange->length = end - mergedRange->start;
- length -= mergedRange->length;
-
- additionalFormat.start = end;
- additionalFormat.length = length;
- }
- }
-
- if (additionalFormat.length > 0)
- mergedFormats->append(additionalFormat);
- }
- }
-
-}
-
-namespace {
-
- class ProtectedLayoutAccessor: public QAbstractTextDocumentLayout
- {
- public:
- inline QTextCharFormat formatAccessor(int pos)
- {
- return format(pos);
- }
- };
-
+ m_engine.reset(new QQuickTextNodeEngine);
+ m_engine->m_hasContents = false;
+ m_engine->setTextColor(textColor);
+ m_engine->setSelectedTextColor(selectedTextColor);
+ m_engine->setSelectionColor(selectionColor);
+ m_engine->setAnchorColor(anchorColor);
}
void QQuickTextNode::addImage(const QRectF &rect, const QImage &image)
@@ -1118,11 +205,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
const QColor &selectionColor, const QColor &selectedTextColor,
int selectionStart, int selectionEnd)
{
- SelectionEngine engine;
- engine.setTextColor(textColor);
- engine.setSelectedTextColor(selectedTextColor);
- engine.setSelectionColor(selectionColor);
- engine.setAnchorColor(anchorColor);
+ initEngine(textColor, selectedTextColor, selectionColor, anchorColor);
QList<QTextFrame *> frames;
frames.append(textDocument->rootFrame());
@@ -1130,7 +213,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QTextFrame *textFrame = frames.takeFirst();
frames.append(textFrame->childFrames());
- engine.addFrameDecorations(textDocument, textFrame);
+ m_engine->addFrameDecorations(textDocument, textFrame);
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
@@ -1140,160 +223,23 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QRectF rect = a->frameBoundingRect(textFrame);
QTextBlock block = textFrame->firstCursorPosition().block();
- engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- engine.addTextObject(rect.topLeft(), format, BinaryTreeNode::Unselected, textDocument,
+ m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ m_engine->addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
pos, textFrame->frameFormat().position());
} else {
QTextFrame::iterator it = textFrame->begin();
while (!it.atEnd()) {
- Q_ASSERT(!engine.currentLine().isValid());
+ Q_ASSERT(!m_engine->currentLine().isValid());
QTextBlock block = it.currentBlock();
-#ifndef QT_NO_IM
- int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
- int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
-#endif
-
- QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- mergeFormats(block.layout(), &colorChanges);
-
- QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft() + position;
- if (QTextList *textList = block.textList()) {
- QPointF pos = blockPosition;
- QTextLayout *layout = block.layout();
- if (layout->lineCount() > 0) {
- QTextLine firstLine = layout->lineAt(0);
- Q_ASSERT(firstLine.isValid());
-
- engine.setCurrentLine(firstLine);
-
- QRectF textRect = firstLine.naturalTextRect();
- pos += textRect.topLeft();
- if (block.textDirection() == Qt::RightToLeft)
- pos.rx() += textRect.width();
-
- const QTextCharFormat charFormat = block.charFormat();
- QFont font(charFormat.font());
- QFontMetricsF fontMetrics(font);
- QTextListFormat listFormat = textList->format();
-
- QString listItemBullet;
- switch (listFormat.style()) {
- case QTextListFormat::ListCircle:
- listItemBullet = QChar(0x25E6); // White bullet
- break;
- case QTextListFormat::ListSquare:
- listItemBullet = QChar(0x25AA); // Black small square
- break;
- case QTextListFormat::ListDecimal:
- case QTextListFormat::ListLowerAlpha:
- case QTextListFormat::ListUpperAlpha:
- case QTextListFormat::ListLowerRoman:
- case QTextListFormat::ListUpperRoman:
- listItemBullet = textList->itemText(block);
- break;
- default:
- listItemBullet = QChar(0x2022); // Black bullet
- break;
- };
-
- QSizeF size(fontMetrics.width(listItemBullet), fontMetrics.height());
- qreal xoff = fontMetrics.width(QLatin1Char(' '));
- if (block.textDirection() == Qt::LeftToRight)
- xoff = -xoff - size.width();
- engine.setPosition(pos + QPointF(xoff, 0));
-
- QTextLayout layout;
- layout.setFont(font);
- layout.setText(listItemBullet); // Bullet
- layout.beginLayout();
- QTextLine line = layout.createLine();
- line.setPosition(QPointF(0, 0));
- layout.endLayout();
-
- QList<QGlyphRun> glyphRuns = layout.glyphRuns();
- for (int i=0; i<glyphRuns.size(); ++i)
- engine.addUnselectedGlyphs(glyphRuns.at(i));
- }
- }
-
- int textPos = block.position();
- QTextBlock::iterator blockIterator = block.begin();
-
- while (!blockIterator.atEnd()) {
- QTextFragment fragment = blockIterator.fragment();
- QString text = fragment.text();
- if (text.isEmpty())
- continue;
-
- QTextCharFormat charFormat = fragment.charFormat();
- engine.setPosition(blockPosition);
- if (text.contains(QChar::ObjectReplacementCharacter)) {
- QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
- if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
- int blockRelativePosition = textPos - block.position();
- QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
- if (!engine.currentLine().isValid()
- || line.lineNumber() != engine.currentLine().lineNumber()) {
- engine.setCurrentLine(line);
- }
-
- BinaryTreeNode::SelectionState selectionState =
- (selectionStart < textPos + text.length()
- && selectionEnd >= textPos)
- ? BinaryTreeNode::Selected
- : BinaryTreeNode::Unselected;
-
- engine.addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos);
- }
- textPos += text.length();
- } else {
- if (charFormat.foreground().style() != Qt::NoBrush)
- engine.setTextColor(charFormat.foreground().color());
- else if (charFormat.isAnchor())
- engine.setTextColor(anchorColor);
- else
- engine.setTextColor(textColor);
-
- int fragmentEnd = textPos + fragment.length();
-#ifndef QT_NO_IM
- if (preeditPosition >= 0
- && preeditPosition >= textPos
- && preeditPosition <= fragmentEnd) {
- fragmentEnd += preeditLength;
- }
-#endif
-
- textPos = engine.addText(block, charFormat, textColor, colorChanges, textPos, fragmentEnd,
- selectionStart, selectionEnd);
- }
-
- ++blockIterator;
- }
-
-#ifndef QT_NO_IM
- if (preeditLength >= 0 && textPos <= block.position() + preeditPosition) {
- engine.setPosition(blockPosition);
- textPos = block.position() + preeditPosition;
- QTextLine line = block.layout()->lineForTextPosition(preeditPosition);
- if (!engine.currentLine().isValid()
- || line.lineNumber() != engine.currentLine().lineNumber()) {
- engine.setCurrentLine(line);
- }
- textPos = engine.addText(block, block.charFormat(), textColor, colorChanges,
- textPos, textPos + preeditLength,
- selectionStart, selectionEnd);
- }
-#endif
-
- engine.setCurrentLine(QTextLine()); // Reset current line because the text layout changed
+ m_engine->addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd);
++it;
}
}
}
- engine.addToSceneGraph(this, style, styleColor);
+ m_engine->addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
@@ -1303,12 +249,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
int selectionStart, int selectionEnd,
int lineStart, int lineCount)
{
- SelectionEngine engine;
- engine.setTextColor(color);
- engine.setSelectedTextColor(selectedTextColor);
- engine.setSelectionColor(selectionColor);
- engine.setAnchorColor(anchorColor);
- engine.setPosition(position);
+ initEngine(color, selectedTextColor, selectionColor, anchorColor);
#ifndef QT_NO_IM
int preeditLength = textLayout->preeditAreaText().length();
@@ -1316,7 +257,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
#endif
QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- mergeFormats(textLayout, &colorChanges);
+ m_engine->mergeFormats(textLayout, &colorChanges);
lineCount = lineCount >= 0
? qMin(lineStart + lineCount, textLayout->lineCount())
@@ -1337,11 +278,11 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
}
#endif
- engine.setCurrentLine(line);
- engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
+ m_engine->setCurrentLine(line);
+ m_engine->addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
}
- engine.addToSceneGraph(this, style, styleColor);
+ m_engine->addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::deleteContent()
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index dcc4ebe22f..16da3ce685 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -49,6 +49,7 @@
#include <QtGui/qcolor.h>
#include <QtGui/qtextlayout.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +63,8 @@ class QSGSimpleRectNode;
class QSGClipNode;
class QSGTexture;
+class QQuickTextNodeEngine;
+
class QQuickTextNode : public QSGTransformNode
{
public:
@@ -104,13 +107,17 @@ public:
void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; }
private:
- void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
+ void initEngine(const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor, const QColor& anchorColor = QColor());
+
QSGContext *m_context;
QSGSimpleRectNode *m_cursorNode;
QList<QSGTexture *> m_textures;
QQuickItem *m_ownerElement;
bool m_useNativeRenderer;
+ QScopedPointer<QQuickTextNodeEngine> m_engine;
+
+ friend class QQuickTextEdit;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
new file mode 100644
index 0000000000..7bbfd1bcda
--- /dev/null
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -0,0 +1,935 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicktextnodeengine_p.h"
+
+#include <QtCore/qpoint.h>
+#include <QtGui/qabstracttextdocumentlayout.h>
+#include <QtGui/qrawfont.h>
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextlayout.h>
+#include <QtGui/qtextobject.h>
+#include <QtGui/qtexttable.h>
+#include <QtGui/qtextlist.h>
+#include <QtQuick/qsgsimplerectnode.h>
+
+#include <private/qquicktext_p_p.h>
+#include <private/qtextdocumentlayout_p.h>
+#include <private/qtextimagehandler_p.h>
+#include <private/qrawfont_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState,
+ QQuickTextNode::Decorations decorations, const QColor &textColor,
+ const QColor &backgroundColor, const QPointF &position)
+{
+ QRectF searchRect = glyphRun.boundingRect();
+ searchRect.translate(position);
+
+ if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
+ return;
+
+ decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration);
+ decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration);
+ decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration);
+ decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
+
+ qreal ascent = glyphRun.rawFont().ascent();
+ insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
+ textColor, backgroundColor, position, ascent));
+}
+
+void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const BinaryTreeNode &binaryTreeNode)
+{
+ int newIndex = binaryTree->size();
+ binaryTree->append(binaryTreeNode);
+ if (newIndex == 0)
+ return;
+
+ int searchIndex = 0;
+ forever {
+ BinaryTreeNode *node = binaryTree->data() + searchIndex;
+ if (binaryTreeNode.boundingRect.left() < node->boundingRect.left()) {
+ if (node->leftChildIndex < 0) {
+ node->leftChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->leftChildIndex;
+ }
+ } else {
+ if (node->rightChildIndex < 0) {
+ node->rightChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->rightChildIndex;
+ }
+ }
+ }
+}
+
+void QQuickTextNodeEngine::BinaryTreeNode::inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
+ QVarLengthArray<int> *sortedIndexes, int currentIndex)
+{
+ Q_ASSERT(currentIndex < binaryTree.size());
+
+ const BinaryTreeNode *node = binaryTree.data() + currentIndex;
+ if (node->leftChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
+
+ sortedIndexes->append(currentIndex);
+
+ if (node->rightChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
+}
+
+
+int QQuickTextNodeEngine::addText(const QTextBlock &block,
+ const QTextCharFormat &charFormat,
+ const QColor &textColor,
+ const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
+ int textPos, int fragmentEnd,
+ int selectionStart, int selectionEnd)
+{
+ if (charFormat.foreground().style() != Qt::NoBrush)
+ setTextColor(charFormat.foreground().color());
+ else
+ setTextColor(textColor);
+
+ while (textPos < fragmentEnd) {
+ int blockRelativePosition = textPos - block.position();
+ QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
+ if (!currentLine().isValid()
+ || line.lineNumber() != currentLine().lineNumber()) {
+ setCurrentLine(line);
+ }
+
+ Q_ASSERT(line.textLength() > 0);
+ int lineEnd = line.textStart() + block.position() + line.textLength();
+
+ int len = qMin(lineEnd - textPos, fragmentEnd - textPos);
+ Q_ASSERT(len > 0);
+
+ int currentStepEnd = textPos + len;
+
+ addGlyphsForRanges(colorChanges,
+ textPos - block.position(),
+ currentStepEnd - block.position(),
+ selectionStart - block.position(),
+ selectionEnd - block.position());
+
+ textPos = currentStepEnd;
+ }
+ return textPos;
+}
+
+void QQuickTextNodeEngine::addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
+ qreal offset, qreal thickness)
+{
+ for (int i=0; i<textDecorations.size(); ++i) {
+ TextDecoration textDecoration = textDecorations.at(i);
+
+ {
+ QRectF &rect = textDecoration.rect;
+ rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
+ rect.setHeight(thickness);
+ }
+
+ m_lines.append(textDecoration);
+ }
+}
+
+void QQuickTextNodeEngine::processCurrentLine()
+{
+ // No glyphs, do nothing
+ if (m_currentLineTree.isEmpty())
+ return;
+
+ // 1. Go through current line and get correct decoration position for each node based on
+ // neighbouring decorations. Add decoration to global list
+ // 2. Create clip nodes for all selected text. Try to merge as many as possible within
+ // the line.
+ // 3. Add QRects to a list of selection rects.
+ // 4. Add all nodes to a global processed list
+ QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
+ BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);
+
+ Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());
+
+ SelectionState currentSelectionState = Unselected;
+ QRectF currentRect;
+
+ QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
+ qreal underlineOffset = 0.0;
+ qreal underlineThickness = 0.0;
+
+ qreal overlineOffset = 0.0;
+ qreal overlineThickness = 0.0;
+
+ qreal strikeOutOffset = 0.0;
+ qreal strikeOutThickness = 0.0;
+
+ QRectF decorationRect = currentRect;
+
+ QColor lastColor;
+ QColor lastBackgroundColor;
+
+ QVarLengthArray<TextDecoration> pendingUnderlines;
+ QVarLengthArray<TextDecoration> pendingOverlines;
+ QVarLengthArray<TextDecoration> pendingStrikeOuts;
+ if (!sortedIndexes.isEmpty()) {
+ QQuickDefaultClipNode *currentClipNode = m_hasSelection ? new QQuickDefaultClipNode(QRectF()) : 0;
+ bool currentClipNodeUsed = false;
+ for (int i=0; i<=sortedIndexes.size(); ++i) {
+ BinaryTreeNode *node = 0;
+ if (i < sortedIndexes.size()) {
+ int sortedIndex = sortedIndexes.at(i);
+ Q_ASSERT(sortedIndex < m_currentLineTree.size());
+
+ node = m_currentLineTree.data() + sortedIndex;
+ }
+
+ if (i == 0)
+ currentSelectionState = node->selectionState;
+
+ // Update decorations
+ if (currentDecorations != QQuickTextNode::NoDecoration) {
+ decorationRect.setY(m_position.y() + m_currentLine.y());
+ decorationRect.setHeight(m_currentLine.height());
+
+ if (node != 0)
+ decorationRect.setRight(node->boundingRect.left());
+
+ TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
+ if (currentDecorations & QQuickTextNode::Underline)
+ pendingUnderlines.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::Overline)
+ pendingOverlines.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::StrikeOut)
+ pendingStrikeOuts.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::Background)
+ m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
+ }
+
+ // If we've reached an unselected node from a selected node, we add the
+ // selection rect to the graph, and we add decoration every time the
+ // selection state changes, because that means the text color changes
+ if (node == 0 || node->selectionState != currentSelectionState) {
+ if (node != 0)
+ currentRect.setRight(node->boundingRect.left());
+ currentRect.setY(m_position.y() + m_currentLine.y());
+ currentRect.setHeight(m_currentLine.height());
+
+ // Draw selection all the way up to the left edge of the unselected item
+ if (currentSelectionState == Selected)
+ m_selectionRects.append(currentRect);
+
+ if (currentClipNode != 0) {
+ if (!currentClipNodeUsed) {
+ delete currentClipNode;
+ } else {
+ currentClipNode->setIsRectangular(true);
+ currentClipNode->setRect(currentRect);
+ currentClipNode->update();
+ }
+ }
+
+ if (node != 0 && m_hasSelection)
+ currentClipNode = new QQuickDefaultClipNode(QRectF());
+ else
+ currentClipNode = 0;
+ currentClipNodeUsed = false;
+
+ if (node != 0) {
+ currentSelectionState = node->selectionState;
+ currentRect = node->boundingRect;
+
+ // Make sure currentRect is valid, otherwise the unite won't work
+ if (currentRect.isNull())
+ currentRect.setSize(QSizeF(1, 1));
+ }
+ } else {
+ if (currentRect.isNull())
+ currentRect = node->boundingRect;
+ else
+ currentRect = currentRect.united(node->boundingRect);
+ }
+
+ if (node != 0) {
+ node->clipNode = currentClipNode;
+ currentClipNodeUsed = true;
+
+ decorationRect = node->boundingRect;
+
+ // If previous item(s) had underline and current does not, then we add the
+ // pending lines to the lists and likewise for overlines and strikeouts
+ if (!pendingUnderlines.isEmpty()
+ && !(node->decorations & QQuickTextNode::Underline)) {
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ pendingUnderlines.clear();
+
+ underlineOffset = 0.0;
+ underlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingOverlines.isEmpty()) {
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ pendingOverlines.clear();
+
+ overlineOffset = 0.0;
+ overlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingStrikeOuts.isEmpty()) {
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+
+ pendingStrikeOuts.clear();
+
+ strikeOutOffset = 0.0;
+ strikeOutThickness = 0.0;
+ }
+
+ // Merge current values with previous. Prefer greatest thickness
+ QRawFont rawFont = node->glyphRun.rawFont();
+ if (node->decorations & QQuickTextNode::Underline) {
+ if (rawFont.lineThickness() > underlineThickness) {
+ underlineThickness = rawFont.lineThickness();
+ underlineOffset = rawFont.underlinePosition();
+ }
+ }
+
+ if (node->decorations & QQuickTextNode::Overline) {
+ overlineOffset = -rawFont.ascent();
+ overlineThickness = rawFont.lineThickness();
+ }
+
+ if (node->decorations & QQuickTextNode::StrikeOut) {
+ strikeOutThickness = rawFont.lineThickness();
+ strikeOutOffset = rawFont.ascent() / -3.0;
+ }
+
+ currentDecorations = node->decorations;
+ lastColor = node->color;
+ lastBackgroundColor = node->backgroundColor;
+ m_processedNodes.append(*node);
+ }
+ }
+
+ if (!pendingUnderlines.isEmpty())
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ if (!pendingOverlines.isEmpty())
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ if (!pendingStrikeOuts.isEmpty())
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+ }
+
+ m_currentLineTree.clear();
+ m_currentLine = QTextLine();
+ m_hasSelection = false;
+}
+
+void QQuickTextNodeEngine::addImage(const QRectF &rect, const QImage &image, qreal ascent,
+ SelectionState selectionState,
+ QTextFrameFormat::Position layoutPosition)
+{
+ QRectF searchRect = rect;
+ if (layoutPosition == QTextFrameFormat::InFlow) {
+ if (m_currentLineTree.isEmpty()) {
+ searchRect.moveTopLeft(m_position + m_currentLine.position());
+ } else {
+ const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1;
+ if (lastNode->glyphRun.isRightToLeft()) {
+ QPointF lastPos = lastNode->boundingRect.topLeft();
+ searchRect.moveTopRight(lastPos - QPointF(0, ascent - lastNode->ascent));
+ } else {
+ QPointF lastPos = lastNode->boundingRect.topRight();
+ searchRect.moveTopLeft(lastPos - QPointF(0, ascent - lastNode->ascent));
+ }
+ }
+ }
+
+ BinaryTreeNode::insert(&m_currentLineTree, searchRect, image, ascent, selectionState);
+ m_hasContents = true;
+}
+
+void QQuickTextNodeEngine::addTextObject(const QPointF &position, const QTextCharFormat &format,
+ SelectionState selectionState,
+ QTextDocument *textDocument, int pos,
+ QTextFrameFormat::Position layoutPosition)
+{
+ QTextObjectInterface *handler = textDocument->documentLayout()->handlerForObject(format.objectType());
+ if (handler != 0) {
+ QImage image;
+ QSizeF size = handler->intrinsicSize(textDocument, pos, format);
+
+ if (format.objectType() == QTextFormat::ImageObject) {
+ QTextImageFormat imageFormat = format.toImageFormat();
+ if (QQuickTextDocumentWithImageResources *imageDoc = qobject_cast<QQuickTextDocumentWithImageResources *>(textDocument)) {
+ image = imageDoc->image(imageFormat);
+
+ if (image.isNull())
+ return;
+ } else {
+ QTextImageHandler *imageHandler = static_cast<QTextImageHandler *>(handler);
+ image = imageHandler->image(textDocument, imageFormat);
+ }
+ }
+
+ if (image.isNull()) {
+ image = QImage(size.toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::transparent);
+ {
+ QPainter painter(&image);
+ handler->drawObject(&painter, image.rect(), textDocument, pos, format);
+ }
+ }
+
+ qreal ascent;
+ QFontMetrics m(format.font());
+ switch (format.verticalAlignment())
+ {
+ case QTextCharFormat::AlignMiddle:
+ ascent = size.height() / 2 - 1;
+ break;
+ case QTextCharFormat::AlignBaseline:
+ ascent = size.height() - m.descent() - 1;
+ break;
+ default:
+ ascent = size.height() - 1;
+ }
+
+ addImage(QRectF(position, size), image, ascent, selectionState, layoutPosition);
+ }
+}
+
+void QQuickTextNodeEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
+{
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Unselected,
+ QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position);
+}
+
+void QQuickTextNodeEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
+{
+ int currentSize = m_currentLineTree.size();
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Selected,
+ QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position);
+ m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
+}
+
+void QQuickTextNodeEngine::addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
+ int start, int end,
+ int selectionStart, int selectionEnd)
+{
+ int currentPosition = start;
+ int remainingLength = end - start;
+ for (int j=0; j<ranges.size(); ++j) {
+ const QTextLayout::FormatRange &range = ranges.at(j);
+ if (range.start + range.length >= currentPosition
+ && range.start < currentPosition + remainingLength) {
+
+ if (range.start > currentPosition) {
+ addGlyphsInRange(currentPosition, range.start - currentPosition,
+ QColor(), QColor(), selectionStart, selectionEnd);
+ }
+ int rangeEnd = qMin(range.start + range.length, currentPosition + remainingLength);
+ QColor rangeColor;
+ if (range.format.hasProperty(QTextFormat::ForegroundBrush))
+ rangeColor = range.format.foreground().color();
+ else if (range.format.isAnchor())
+ rangeColor = m_anchorColor;
+ QColor rangeBackgroundColor = range.format.hasProperty(QTextFormat::BackgroundBrush)
+ ? range.format.background().color()
+ : QColor();
+
+ addGlyphsInRange(range.start, rangeEnd - range.start,
+ rangeColor, rangeBackgroundColor,
+ selectionStart, selectionEnd);
+
+ currentPosition = range.start + range.length;
+ remainingLength = end - currentPosition;
+
+ } else if (range.start > currentPosition + remainingLength || remainingLength <= 0) {
+ break;
+ }
+ }
+
+ if (remainingLength > 0) {
+ addGlyphsInRange(currentPosition, remainingLength, QColor(), QColor(),
+ selectionStart, selectionEnd);
+ }
+
+}
+
+void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength,
+ const QColor &color, const QColor &backgroundColor,
+ int selectionStart, int selectionEnd)
+{
+ QColor oldColor;
+ if (color.isValid()) {
+ oldColor = m_textColor;
+ m_textColor = color;
+ }
+
+ QColor oldBackgroundColor = m_backgroundColor;
+ if (backgroundColor.isValid()) {
+ oldBackgroundColor = m_backgroundColor;
+ m_backgroundColor = backgroundColor;
+ }
+
+ bool hasSelection = selectionEnd >= 0
+ && selectionStart <= selectionEnd;
+
+ QTextLine &line = m_currentLine;
+ int rangeEnd = rangeStart + rangeLength;
+ if (!hasSelection || (selectionStart > rangeEnd || selectionEnd < rangeStart)) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ } else {
+ if (rangeStart < selectionStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart,
+ qMin(selectionStart - rangeStart,
+ rangeLength));
+
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ }
+
+ if (rangeEnd > selectionStart) {
+ int start = qMax(selectionStart, rangeStart);
+ int length = qMin(selectionEnd - start + 1, rangeEnd - start);
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(start, length);
+
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addSelectedGlyphs(glyphRun);
+ }
+ }
+
+ if (selectionEnd >= rangeStart && selectionEnd < rangeEnd) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, rangeEnd - selectionEnd - 1);
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ }
+ }
+
+ if (backgroundColor.isValid())
+ m_backgroundColor = oldBackgroundColor;
+
+ if (oldColor.isValid())
+ m_textColor = oldColor;
+}
+
+void QQuickTextNodeEngine::addBorder(const QRectF &rect, qreal border,
+ QTextFrameFormat::BorderStyle borderStyle,
+ const QBrush &borderBrush)
+{
+ QColor color = borderBrush.color();
+
+ // Currently we don't support other styles than solid
+ Q_UNUSED(borderStyle);
+
+ m_backgrounds.append(qMakePair(QRectF(rect.left(), rect.top(), border, rect.height() + border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.top(), rect.width(), border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.right(), rect.top() + border, border, rect.height() - border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.bottom(), rect.width(), border), color));
+}
+
+void QQuickTextNodeEngine::addFrameDecorations(QTextDocument *document, QTextFrame *frame)
+{
+ QTextDocumentLayout *documentLayout = qobject_cast<QTextDocumentLayout *>(document->documentLayout());
+ QTextFrameFormat frameFormat = frame->format().toFrameFormat();
+
+ QTextTable *table = qobject_cast<QTextTable *>(frame);
+ QRectF boundingRect = table == 0
+ ? documentLayout->frameBoundingRect(frame)
+ : documentLayout->tableBoundingRect(table);
+
+ QBrush bg = frame->frameFormat().background();
+ if (bg.style() != Qt::NoBrush)
+ m_backgrounds.append(qMakePair(boundingRect, bg.color()));
+
+ if (!frameFormat.hasProperty(QTextFormat::FrameBorder))
+ return;
+
+ qreal borderWidth = frameFormat.border();
+ if (qFuzzyIsNull(borderWidth))
+ return;
+
+ QBrush borderBrush = frameFormat.borderBrush();
+ QTextFrameFormat::BorderStyle borderStyle = frameFormat.borderStyle();
+ if (borderStyle == QTextFrameFormat::BorderStyle_None)
+ return;
+
+ addBorder(boundingRect.adjusted(frameFormat.leftMargin(), frameFormat.topMargin(),
+ -frameFormat.rightMargin(), -frameFormat.bottomMargin()),
+ borderWidth, borderStyle, borderBrush);
+ if (table != 0) {
+ int rows = table->rows();
+ int columns = table->columns();
+
+ for (int row=0; row<rows; ++row) {
+ for (int column=0; column<columns; ++column) {
+ QTextTableCell cell = table->cellAt(row, column);
+
+ QRectF cellRect = documentLayout->tableCellBoundingRect(table, cell);
+ addBorder(cellRect.adjusted(-borderWidth, -borderWidth, 0, 0), borderWidth,
+ borderStyle, borderBrush);
+ }
+ }
+ }
+}
+
+void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
+ QQuickText::TextStyle style,
+ const QColor &styleColor)
+{
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+
+ for (int i=0; i<m_backgrounds.size(); ++i) {
+ const QRectF &rect = m_backgrounds.at(i).first;
+ const QColor &color = m_backgrounds.at(i).second;
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(rect, color));
+ }
+
+ // First, prepend all selection rectangles to the tree
+ for (int i=0; i<m_selectionRects.size(); ++i) {
+ const QRectF &rect = m_selectionRects.at(i);
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
+ }
+
+ // Finally, add decorations for each node to the tree.
+ for (int i=0; i<m_lines.size(); ++i) {
+ const TextDecoration &textDecoration = m_lines.at(i);
+
+ QColor color = textDecoration.selectionState == Selected
+ ? m_selectedTextColor
+ : textDecoration.color;
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
+ }
+
+ // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
+ // font, selection state and clip node.
+ typedef QPair<QFontEngine *, QPair<QQuickDefaultClipNode *, QPair<QRgb, int> > > KeyType;
+ QHash<KeyType, BinaryTreeNode *> map;
+ QList<BinaryTreeNode *> nodes;
+ for (int i = 0; i < m_processedNodes.size(); ++i) {
+ BinaryTreeNode *node = m_processedNodes.data() + i;
+
+ if (node->image.isNull()) {
+ QGlyphRun glyphRun = node->glyphRun;
+ QRawFont rawFont = glyphRun.rawFont();
+ QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
+
+ QFontEngine *fontEngine = rawFontD->fontEngine;
+
+ KeyType key(qMakePair(fontEngine,
+ qMakePair(node->clipNode,
+ qMakePair(node->color.rgba(), int(node->selectionState)))));
+
+ BinaryTreeNode *otherNode = map.value(key, 0);
+ if (otherNode != 0) {
+ QGlyphRun &otherGlyphRun = otherNode->glyphRun;
+
+ QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
+ QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();
+
+ otherGlyphIndexes += glyphRun.glyphIndexes();
+
+ QVector<QPointF> glyphPositions = glyphRun.positions();
+ otherGlyphPositions.reserve(otherGlyphPositions.size() + glyphPositions.size());
+ for (int j = 0; j < glyphPositions.size(); ++j) {
+ otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
+ }
+
+ otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
+ otherGlyphRun.setPositions(otherGlyphPositions);
+
+ } else {
+ map.insert(key, node);
+ nodes.append(node);
+ }
+ } else {
+ parentNode->addImage(node->boundingRect, node->image);
+ if (node->selectionState == Selected) {
+ QColor color = m_selectionColor;
+ color.setAlpha(128);
+ parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color));
+ }
+ }
+ }
+
+ foreach (const BinaryTreeNode *node, nodes) {
+
+ QQuickDefaultClipNode *clipNode = node->clipNode;
+ if (clipNode != 0 && clipNode->parent() == 0 )
+ parentNode->appendChildNode(clipNode);
+
+ QColor color = node->selectionState == Selected
+ ? m_selectedTextColor
+ : node->color;
+
+ parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
+ }
+}
+
+void QQuickTextNodeEngine::mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats)
+{
+ Q_ASSERT(mergedFormats != 0);
+ if (textLayout == 0)
+ return;
+
+ QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+ for (int i=0; i<additionalFormats.size(); ++i) {
+ QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
+ if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
+ || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)
+ || additionalFormat.format.isAnchor()) {
+ // Merge overlapping formats
+ if (!mergedFormats->isEmpty()) {
+ QTextLayout::FormatRange *lastFormat = mergedFormats->data() + mergedFormats->size() - 1;
+
+ if (additionalFormat.start < lastFormat->start + lastFormat->length) {
+ QTextLayout::FormatRange *mergedRange = 0;
+
+ int length = additionalFormat.length;
+ if (additionalFormat.start > lastFormat->start) {
+ lastFormat->length = additionalFormat.start - lastFormat->start;
+ length -= lastFormat->length;
+
+ mergedFormats->append(QTextLayout::FormatRange());
+ mergedRange = mergedFormats->data() + mergedFormats->size() - 1;
+ lastFormat = mergedFormats->data() + mergedFormats->size() - 2;
+ } else {
+ mergedRange = lastFormat;
+ }
+
+ mergedRange->format = lastFormat->format;
+ mergedRange->format.merge(additionalFormat.format);
+ mergedRange->start = additionalFormat.start;
+
+ int end = qMin(additionalFormat.start + additionalFormat.length,
+ lastFormat->start + lastFormat->length);
+
+ mergedRange->length = end - mergedRange->start;
+ length -= mergedRange->length;
+
+ additionalFormat.start = end;
+ additionalFormat.length = length;
+ }
+ }
+
+ if (additionalFormat.length > 0)
+ mergedFormats->append(additionalFormat);
+ }
+ }
+
+}
+
+void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QTextBlock &block, const QPointF &position, const QColor &textColor, const QColor &anchorColor, int selectionStart, int selectionEnd)
+{
+ Q_ASSERT(textDocument);
+#ifndef QT_NO_IM
+ int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
+ int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
+#endif
+
+ QVarLengthArray<QTextLayout::FormatRange> colorChanges;
+ mergeFormats(block.layout(), &colorChanges);
+
+ QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft() + position;
+ if (QTextList *textList = block.textList()) {
+ QPointF pos = blockPosition;
+ QTextLayout *layout = block.layout();
+ if (layout->lineCount() > 0) {
+ QTextLine firstLine = layout->lineAt(0);
+ Q_ASSERT(firstLine.isValid());
+
+ setCurrentLine(firstLine);
+
+ QRectF textRect = firstLine.naturalTextRect();
+ pos += textRect.topLeft();
+ if (block.textDirection() == Qt::RightToLeft)
+ pos.rx() += textRect.width();
+
+ const QTextCharFormat charFormat = block.charFormat();
+ QFont font(charFormat.font());
+ QFontMetricsF fontMetrics(font);
+ QTextListFormat listFormat = textList->format();
+
+ QString listItemBullet;
+ switch (listFormat.style()) {
+ case QTextListFormat::ListCircle:
+ listItemBullet = QChar(0x25E6); // White bullet
+ break;
+ case QTextListFormat::ListSquare:
+ listItemBullet = QChar(0x25AA); // Black small square
+ break;
+ case QTextListFormat::ListDecimal:
+ case QTextListFormat::ListLowerAlpha:
+ case QTextListFormat::ListUpperAlpha:
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman:
+ listItemBullet = textList->itemText(block);
+ break;
+ default:
+ listItemBullet = QChar(0x2022); // Black bullet
+ break;
+ };
+
+ QSizeF size(fontMetrics.width(listItemBullet), fontMetrics.height());
+ qreal xoff = fontMetrics.width(QLatin1Char(' '));
+ if (block.textDirection() == Qt::LeftToRight)
+ xoff = -xoff - size.width();
+ setPosition(pos + QPointF(xoff, 0));
+
+ QTextLayout layout;
+ layout.setFont(font);
+ layout.setText(listItemBullet); // Bullet
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setPosition(QPointF(0, 0));
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ for (int i=0; i<glyphRuns.size(); ++i)
+ addUnselectedGlyphs(glyphRuns.at(i));
+ }
+ }
+
+ int textPos = block.position();
+ QTextBlock::iterator blockIterator = block.begin();
+
+ while (!blockIterator.atEnd()) {
+ QTextFragment fragment = blockIterator.fragment();
+ QString text = fragment.text();
+ if (text.isEmpty())
+ continue;
+
+ QTextCharFormat charFormat = fragment.charFormat();
+ setPosition(blockPosition);
+ if (text.contains(QChar::ObjectReplacementCharacter)) {
+ QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
+ if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
+ int blockRelativePosition = textPos - block.position();
+ QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
+ if (!currentLine().isValid()
+ || line.lineNumber() != currentLine().lineNumber()) {
+ setCurrentLine(line);
+ }
+
+ QQuickTextNodeEngine::SelectionState selectionState =
+ (selectionStart < textPos + text.length()
+ && selectionEnd >= textPos)
+ ? QQuickTextNodeEngine::Selected
+ : QQuickTextNodeEngine::Unselected;
+
+ addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos);
+ }
+ textPos += text.length();
+ } else {
+ if (charFormat.foreground().style() != Qt::NoBrush)
+ setTextColor(charFormat.foreground().color());
+ else if (charFormat.isAnchor())
+ setTextColor(anchorColor);
+ else
+ setTextColor(textColor);
+
+ int fragmentEnd = textPos + fragment.length();
+#ifndef QT_NO_IM
+ if (preeditPosition >= 0
+ && preeditPosition >= textPos
+ && preeditPosition <= fragmentEnd) {
+ fragmentEnd += preeditLength;
+ }
+#endif
+
+ textPos = addText(block, charFormat, textColor, colorChanges, textPos, fragmentEnd,
+ selectionStart, selectionEnd);
+ }
+
+ ++blockIterator;
+ }
+
+#ifndef QT_NO_IM
+ if (preeditLength >= 0 && textPos <= block.position() + preeditPosition) {
+ setPosition(blockPosition);
+ textPos = block.position() + preeditPosition;
+ QTextLine line = block.layout()->lineForTextPosition(preeditPosition);
+ if (!currentLine().isValid()
+ || line.lineNumber() != currentLine().lineNumber()) {
+ setCurrentLine(line);
+ }
+ textPos = addText(block, block.charFormat(), textColor, colorChanges,
+ textPos, textPos + preeditLength,
+ selectionStart, selectionEnd);
+ }
+#endif
+
+ setCurrentLine(QTextLine()); // Reset current line because the text layout changed
+ m_hasContents = true;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h
new file mode 100644
index 0000000000..6a98d6b470
--- /dev/null
+++ b/src/quick/items/qquicktextnodeengine_p.h
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qlist.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qglyphrun.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextlayout.h>
+#include "qquickclipnode_p.h"
+#include "qquicktextnode_p.h"
+
+#ifndef QQUICKTEXTNODEENGINE_P_H
+#define QQUICKTEXTNODEENGINE_P_H
+
+QT_BEGIN_NAMESPACE
+
+// Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
+// and rectangle nodes to represent the text, decorations and selection. Will try to minimize
+// number of nodes, and join decorations in neighbouring items
+
+class QQuickTextNodeEngine {
+
+public:
+
+ enum SelectionState {
+ Unselected,
+ Selected
+ };
+
+ struct BinaryTreeNode {
+
+ BinaryTreeNode()
+ : selectionState(Unselected), clipNode(0), decorations(QQuickTextNode::NoDecoration)
+ , ascent(0.0), leftChildIndex(-1), rightChildIndex(-1)
+ {
+ }
+
+ BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a)
+ : boundingRect(brect), selectionState(selState), clipNode(0), decorations(QQuickTextNode::NoDecoration)
+ , image(i), ascent(a), leftChildIndex(-1), rightChildIndex(-1)
+ {
+ }
+
+ BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
+ const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc,
+ const QPointF &pos, qreal a)
+ : glyphRun(g), boundingRect(brect), selectionState(selState), clipNode(0), decorations(decs)
+ , color(c), backgroundColor(bc), position(pos), ascent(a), leftChildIndex(-1), rightChildIndex(-1)
+ {
+ }
+
+ QGlyphRun glyphRun;
+ QRectF boundingRect;
+ SelectionState selectionState;
+ QQuickDefaultClipNode *clipNode;
+ QQuickTextNode::Decorations decorations;
+ QColor color;
+ QColor backgroundColor;
+ QPointF position;
+ QImage image;
+ qreal ascent;
+
+ int leftChildIndex;
+ int rightChildIndex;
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const QRectF &rect, const QImage &image, qreal ascent, SelectionState selectionState)
+ { insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent)); }
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState,
+ QQuickTextNode::Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position);
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const BinaryTreeNode &binaryTreeNode);
+ static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree, QVarLengthArray<int> *sortedIndexes, int currentIndex = 0);
+ };
+
+ QQuickTextNodeEngine() : m_hasSelection(false), m_hasContents(false) {}
+
+ bool hasContents() const { return m_hasContents; }
+ void addTextBlock(QTextDocument *, const QTextBlock &, const QPointF &position, const QColor &textColor, const QColor& anchorColor, int selectionStart, int selectionEnd);
+ QTextLine currentLine() const { return m_currentLine; }
+
+ void setCurrentLine(const QTextLine &currentLine)
+ {
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+ m_currentLine = currentLine;
+ }
+
+ void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle,
+ const QBrush &borderBrush);
+ void addFrameDecorations(QTextDocument *document, QTextFrame *frame);
+ void addImage(const QRectF &rect, const QImage &image, qreal ascent,
+ SelectionState selectionState,
+ QTextFrameFormat::Position layoutPosition);
+ int addText(const QTextBlock &block,
+ const QTextCharFormat &charFormat,
+ const QColor &textColor,
+ const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
+ int textPos, int fragmentEnd,
+ int selectionStart, int selectionEnd);
+ void addTextObject(const QPointF &position, const QTextCharFormat &format,
+ SelectionState selectionState,
+ QTextDocument *textDocument, int pos,
+ QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
+ void addSelectedGlyphs(const QGlyphRun &glyphRun);
+ void addUnselectedGlyphs(const QGlyphRun &glyphRun);
+ void addGlyphsInRange(int rangeStart, int rangeEnd,
+ const QColor &color, const QColor &backgroundColor,
+ int selectionStart, int selectionEnd);
+ void addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
+ int start, int end,
+ int selectionStart, int selectionEnd);
+
+ void addToSceneGraph(QQuickTextNode *parent,
+ QQuickText::TextStyle style = QQuickText::Normal,
+ const QColor &styleColor = QColor());
+
+ void setSelectionColor(const QColor &selectionColor)
+ {
+ m_selectionColor = selectionColor;
+ }
+
+ void setSelectedTextColor(const QColor &selectedTextColor)
+ {
+ m_selectedTextColor = selectedTextColor;
+ }
+
+ void setTextColor(const QColor &textColor)
+ {
+ m_textColor = textColor;
+ }
+
+ void setAnchorColor(const QColor &anchorColor)
+ {
+ m_anchorColor = anchorColor;
+ }
+
+ void setPosition(const QPointF &position)
+ {
+ m_position = position;
+ }
+
+
+
+
+private:
+ struct TextDecoration
+ {
+ TextDecoration() : selectionState(Unselected) {}
+ TextDecoration(const SelectionState &s,
+ const QRectF &r,
+ const QColor &c)
+ : selectionState(s)
+ , rect(r)
+ , color(c)
+ {
+ }
+
+ SelectionState selectionState;
+ QRectF rect;
+ QColor color;
+ };
+
+ void processCurrentLine();
+ void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations, qreal offset, qreal thickness);
+ void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
+
+ QColor m_selectionColor;
+ QColor m_textColor;
+ QColor m_backgroundColor;
+ QColor m_selectedTextColor;
+ QColor m_anchorColor;
+ QPointF m_position;
+
+ QTextLine m_currentLine;
+
+ QList<QPair<QRectF, QColor> > m_backgrounds;
+ QList<QRectF> m_selectionRects;
+ QVarLengthArray<BinaryTreeNode> m_currentLineTree;
+
+ QList<TextDecoration> m_lines;
+ QVector<BinaryTreeNode> m_processedNodes;
+
+ QList<QPair<QRectF, QImage> > m_images;
+
+ bool m_hasSelection : 1;
+ bool m_hasContents : 1;
+ friend class QQuickTextNode;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKTEXTNODEENGINE_P_H
diff --git a/src/quick/items/qquickthreadedwindowmanager.cpp b/src/quick/items/qquickthreadedwindowmanager.cpp
deleted file mode 100644
index 6c7b9c0448..0000000000
--- a/src/quick/items/qquickthreadedwindowmanager.cpp
+++ /dev/null
@@ -1,910 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickwindowmanager_p.h"
-#include "qquickthreadedwindowmanager_p.h"
-
-#include <QtCore/QTime>
-#include <QtCore/QDebug>
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include <QtQml/private/qqmlglobal_p.h>
-
-#include <QtQuick/QQuickWindow>
-#include <QtQuick/private/qquickwindow_p.h>
-
-QT_BEGIN_NAMESPACE
-
-//#define THREAD_DEBUG
-extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-
-const QEvent::Type QEvent_Sync = QEvent::Type(QEvent::User);
-const QEvent::Type QEvent_DeferredUpdate = QEvent::Type(QEvent::User + 1);
-
-#define QQUICK_RENDER_TIMING
-#ifdef QQUICK_RENDER_TIMING
-DEFINE_BOOL_CONFIG_OPTION(qquick_render_timing, QML_RENDER_TIMING)
-static QTime threadTimer;
-static int syncTime;
-static int renderTime;
-static int swapTime;
-#endif
-
-
-/*
- Threaded Rendering
- ==================
-
- The threaded rendering uses a number of different variables to track potential
- states used to handle resizing, initial paint, grabbing and driving animations
- while ALWAYS keeping the GL context in the rendering thread and keeping the
- overhead of normal one-shot paints and vblank driven animations at a minimum.
-
- Resize, initial show and grab suffer slightly in this model as they are locked
- to the rendering in the rendering thread, but this is a necessary evil for
- the system to work.
-
- Variables that are used:
-
- Private::animationRunning: This is true while the animations are running, and only
- written to inside locks.
-
- RenderThread::isGuiLocked: This is used to indicate that the GUI thread owns the
- lock. This variable is an integer to allow for recursive calls to lockInGui()
- without using a recursive mutex. See isPostingSyncEvent.
-
- RenderThread::isPostingSyncEvent: This variable is set in the render thread just
- before the sync event is sent to the GUI thread. It is used to avoid deadlocks
- in the case where render thread waits while waiting for GUI to pick up the sync
- event and GUI thread gets a resizeEvent, the initial paintEvent or a grab.
- When this happens, we use the
- exhaustSyncEvent() function to do the sync right there and mark the coming
- sync event to be discarded. There can only ever be one sync incoming.
-
- RenderThread::isRenderBlock: This variable is true when animations are not
- running and the render thread has gone to sleep, waiting for more to do.
-
- RenderThread::isExternalUpdatePending: This variable is set to false when
- a new render pass is started and to true in maybeUpdate(). It is an
- indication to the render thread that another render pass needs to take
- place, rather than the render thread going to sleep after completing its swap.
-
- RenderThread::doGrab: This variable is set by the grab() function and
- tells the renderer to do a grab after rendering is complete and before
- swapping happens.
-
- RenderThread::shouldExit: This variable is used to determine if the render
- thread should do a nother pass. It is typically set as a result of show()
- and unset as a result of hide() or during shutdown()
-
- RenderThread::hasExited: Used by the GUI thread to synchronize the shutdown
- after shouldExit has been set to true.
- */
-
-
-void QQuickRenderThreadSingleContextWindowManager::initialize()
-{
- Q_ASSERT(m_rendered_windows.size());
-
- QQuickWindow *win = 0;
- for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin();
- it != m_rendered_windows.constEnd() && !win; ++it) {
- if (QQuickWindowPrivate::get(it.key())->isRenderable())
- win = it.key();
- }
- if (!win)
- return;
-
- gl = new QOpenGLContext();
- // Pick up the surface format from one of them
- gl->setFormat(win->requestedFormat());
- gl->create();
- if (!gl->makeCurrent(win))
- qWarning("QQuickWindow: makeCurrent() failed...");
-
- Q_ASSERT(!sg->isReady());
- sg->initialize(gl);
-}
-
-
-/*!
- This function is called when the window is created to register the window with
- the window manager.
-
- Called on GUI Thread.
- */
-
-void QQuickRenderThreadSingleContextWindowManager::show(QQuickWindow *window)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Window added to windowing system, %p, %dx%d\n", window, window->width(), window->height());
-#endif
-
- WindowTracker tracker;
- tracker.window = window;
- tracker.isVisible = false;
- tracker.toBeRemoved = false;
- m_tracked_windows << tracker;
-
- connect(window, SIGNAL(widthChanged(int)), this, SLOT(windowVisibilityChanged()), Qt::DirectConnection);
- connect(window, SIGNAL(heightChanged(int)), this, SLOT(windowVisibilityChanged()), Qt::DirectConnection);
-
- windowVisibilityChanged();
-}
-
-
-void QQuickRenderThreadSingleContextWindowManager::handleAddedWindow(QQuickWindow *window)
-{
-#ifdef THREAD_DEBUG
- printf(" RenderThread: adding window: %p\n", window);
-#endif
-
- WindowData *data = new WindowData;
- data->sizeWasChanged = false;
- data->windowSize = window->size();
- data->isVisible = window->isVisible();
- data->isRenderable = QQuickWindowPrivate::get(window)->isRenderable();
- m_rendered_windows[window] = data;
-
- isExternalUpdatePending = true;
-}
-
-
-/*!
- Called on Render Thread
- */
-void QQuickRenderThreadSingleContextWindowManager::handleAddedWindows()
-{
-#ifdef THREAD_DEBUG
- printf(" RenderThread: about to add %d\n", m_added_windows.size());
-#endif
-
- while (m_added_windows.size()) {
- QQuickWindow *window = m_added_windows.takeLast();
- handleAddedWindow(window);
- }
-}
-
-
-/*!
- Called on the GUI Thread, from the window' destructor
- */
-
-void QQuickRenderThreadSingleContextWindowManager::windowDestroyed(QQuickWindow *window)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Window destroyed: %p\n", window);
-#endif
-
- hide(window);
-}
-
-
-/*!
- Called on GUI Thread
- */
-
-void QQuickRenderThreadSingleContextWindowManager::hide(QQuickWindow *window)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Window hidden: %p\n", window);
-#endif
-
- int position = -1;
- for (int i=0; i<m_tracked_windows.size(); ++i) {
- if (m_tracked_windows.at(i).window == window) {
- m_tracked_windows[i].toBeRemoved = true;
- position = i;
- break;
- }
- }
-
- if (position >= 0) {
- disconnect(window, SIGNAL(widthChanged(int)), this, SLOT(windowVisibilityChanged()));
- disconnect(window, SIGNAL(heightChanged(int)), this, SLOT(windowVisibilityChanged()));
- windowVisibilityChanged();
- m_tracked_windows.removeAt(position);
- }
-
-#ifdef THREAD_DEBUG
- printf("GUI: Window removal completed... %p\n", window);
-#endif
-}
-
-/*!
- Called on Render Thread
- */
-void QQuickRenderThreadSingleContextWindowManager::handleRemovedWindows(bool clearGLContext)
-{
-#ifdef THREAD_DEBUG
- printf(" RenderThread: about to remove %d\n", m_removed_windows.size());
-#endif
-
- bool removedAnything = false;
- while (m_removed_windows.size()) {
- QQuickWindow *window = m_removed_windows.takeLast();
-#ifdef THREAD_DEBUG
- printf(" RenderThread: removing %p\n", window);
-#endif
-
- QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown();
- delete m_rendered_windows.take(window);
- removedAnything = true;
- }
-
- // If a window is removed because it has been hidden it will take with it
- // the gl context (at least on Mac) if bound, so disconnect the gl context
- // from anything
- if (removedAnything && clearGLContext)
- gl->doneCurrent();
-}
-
-
-
-/*!
- Called on GUI Thread
- */
-
-void QQuickRenderThreadSingleContextWindowManager::windowVisibilityChanged()
-{
- bool anyoneShowing = false;
- QList<QQuickWindow *> toAdd, toRemove;
-
- // Not optimal, but also not frequently used...
- for (int i=0; i<m_tracked_windows.size(); ++i) {
- WindowTracker &t = const_cast<WindowTracker &>(m_tracked_windows.at(i));
- QQuickWindow *win = t.window;
-
- Q_ASSERT(win->isVisible() || QQuickWindowPrivate::get(win)->renderWithoutShowing || t.toBeRemoved);
- bool windowVisible = win->width() > 0 && win->height() > 0;
- anyoneShowing |= (windowVisible && !t.toBeRemoved);
-
- if ((!windowVisible && t.isVisible) || t.toBeRemoved) {
- toRemove << win;
- } else if (windowVisible && !t.isVisible) {
- toAdd << win;
- }
- t.isVisible = windowVisible;
- }
-
- if (isRunning()) {
- if (!anyoneShowing) {
- stopRendering();
- } else {
- lockInGui();
- exhaustSyncEvent();
- m_added_windows << toAdd;
- m_removed_windows << toRemove;
- while (isRunning() && (m_added_windows.size() || m_removed_windows.size())) {
- if (isRenderBlocked)
- wake();
- wait();
- }
- unlockInGui();
- }
-
- } else if (anyoneShowing) {
- Q_ASSERT(toRemove.isEmpty()); // since loop is not running, nothing is showing now
- for (int i=0; i<toAdd.size(); ++i)
- handleAddedWindow(toAdd.at(i));
- startRendering();
- }
-
-}
-
-
-void QQuickRenderThreadSingleContextWindowManager::run()
-{
-#ifdef THREAD_DEBUG
- printf("QML Rendering Thread Started\n");
-#endif
-
- lock();
- Q_ASSERT(!gl);
- initialize();
- // Wake GUI as it is waiting for the GL context to have appeared, as
- // an indication that the render thread is now running.
- wake();
- unlock();
-
- if (!gl)
- return;
-
- while (!shouldExit) {
- lock();
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: *** NEW FRAME ***\n");
-#endif
-
- isExternalUpdatePending = false;
- handleAddedWindows();
-
- if (!isGuiLocked) {
- isPostingSyncEvent = true;
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: acquired sync lock...\n");
-#endif
- QCoreApplication::postEvent(this, new QEvent(QEvent_Sync));
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: going to sleep...\n");
-#endif
- wake(); // In case the event got through all the way to wait() before this thread got to wait.
- wait();
-
-
- isPostingSyncEvent = false;
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: Doing locked sync\n");
-#endif
-#ifdef QQUICK_RENDER_TIMING
- if (qquick_render_timing())
- threadTimer.start();
-#endif
- inSync = true;
- for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin();
- it != m_rendered_windows.constEnd(); ++it) {
- QQuickWindow *window = it.key();
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: Syncing window: %p\n", window);
-#endif
-
- WindowData *windowData = it.value();
- QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window);
-
- windowData->isRenderable = windowPrivate->isRenderable();
-
- if (windowData->isRenderable) {
- gl->makeCurrent(window);
-
- if (windowData->viewportSize != windowData->windowSize) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: --- window has changed size...\n");
-#endif
- windowData->viewportSize = windowData->windowSize;
- windowData->sizeWasChanged = true;
- glViewport(0, 0, windowData->viewportSize.width(), windowData->viewportSize.height());
- }
-
- windowPrivate->syncSceneGraph();
- }
- }
- inSync = false;
-
- // Wake GUI after sync to let it continue animating and event processing.
- wake();
- unlock();
-#ifdef THREAD_DEBUG
- printf(" RenderThread: sync done\n");
-#endif
-#ifdef QQUICK_RENDER_TIMING
- if (qquick_render_timing())
- syncTime = threadTimer.elapsed();
-#endif
-
- for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin();
- it != m_rendered_windows.constEnd(); ++it) {
- QQuickWindow *window = it.key();
- WindowData *windowData = it.value();
- QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window);
-
- if (!windowData->isRenderable)
- continue;
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: Rendering window %p\n", window);
-#endif
-
- Q_ASSERT(windowData->windowSize.width() > 0 && windowData->windowSize.height() > 0);
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: --- rendering at size %dx%d\n",
- windowData->viewportSize.width(), windowData->viewportSize.height()
- );
-#endif
-
- // We only need to re-makeCurrent when we have multiple surfaces.
- if (m_rendered_windows.size() > 1)
- gl->makeCurrent(window);
-
- windowPrivate->renderSceneGraph(windowData->viewportSize);
-#ifdef QQUICK_RENDER_TIMING
- if (qquick_render_timing())
- renderTime = threadTimer.elapsed() - syncTime;
-#endif
-
- // The content of the target buffer is undefined after swap() so grab needs
- // to happen before swap();
- if (window == windowToGrab) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: --- grabbing...\n");
-#endif
- grabContent = qt_gl_read_framebuffer(windowData->windowSize, false, false);
- windowToGrab = 0;
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: --- wait for swap...\n");
-#endif
-
- if (windowData->isVisible && window->isExposed())
- gl->swapBuffers(window);
-
- windowPrivate->fireFrameSwapped();
-#ifdef THREAD_DEBUG
- printf(" RenderThread: --- swap complete...\n");
-#endif
-
- }
-
-#ifdef QQUICK_RENDER_TIMING
- if (qquick_render_timing()) {
- static QTime lastFrameTime = QTime::currentTime();
- swapTime = threadTimer.elapsed() - renderTime - syncTime;
- qDebug() << "- Breakdown of frame time; sync:" << syncTime
- << "ms render:" << renderTime << "ms swap:" << swapTime
- << "ms total:" << swapTime + renderTime + syncTime
- << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime()))
- << "ms";
- lastFrameTime = QTime::currentTime();
- }
-#endif
-
- lock();
-
- handleRemovedWindows();
-
- // Update sizes...
- for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin();
- it != m_rendered_windows.constEnd(); ++it) {
- WindowData *windowData = it.value();
- if (windowData->sizeWasChanged) {
- windowData->renderedSize = windowData->viewportSize;
- windowData->sizeWasChanged = false;
- }
- }
-
-
- // Wake the GUI thread now that rendering is complete, to signal that painting
- // is done, resizing is done or grabbing is completed. For grabbing, we're
- // signalling this much later than needed (we could have done it before swap)
- // but we don't want to lock an extra time.
- wake();
-
- if (!animationRunning && !isExternalUpdatePending && !shouldExit && !windowToGrab) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: nothing to do, going to sleep...\n");
-#endif
- isRenderBlocked = true;
- wait();
- isRenderBlocked = false;
- }
-
- unlock();
-
- QCoreApplication::processEvents();
-
- // Process any "deleteLater" objects...
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: deleting all outstanding nodes\n");
-#endif
-
- m_removed_windows << m_rendered_windows.keys();
- handleRemovedWindows(false);
-
- sg->invalidate();
-
- gl->doneCurrent();
- delete gl;
- gl = 0;
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: render loop exited... Good Night!\n");
-#endif
-
- lock();
- hasExited = true;
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: waking GUI for final sleep..\n");
-#endif
- wake();
- unlock();
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: All done...\n");
-#endif
-}
-
-bool QQuickRenderThreadSingleContextWindowManager::event(QEvent *e)
-{
- Q_ASSERT(QThread::currentThread() == qApp->thread());
-
- if (e->type() == QEvent_Sync) {
-
- // If all windowes have been hidden, ignore the event
- if (!isRunning())
- return true;
-
- if (!syncAlreadyHappened)
- sync(false);
-
- syncAlreadyHappened = false;
-
- if (animationRunning) {
-#ifdef THREAD_DEBUG
- printf("GUI: Advancing animations...\n");
-#endif
-
- animDriver->advance();
-
-#ifdef THREAD_DEBUG
- printf("GUI: Animations advanced...\n");
-#endif
- }
-
- return true;
- } else if (e->type() == QEvent_DeferredUpdate) {
- handleDeferredUpdate();
-
- } else if (e->type() == QEvent::Timer) {
-#ifdef THREAD_DEBUG
- printf("GUI: Animations advanced via timer...\n");
-#endif
- animDriver->advance();
- }
-
- return QThread::event(e);
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::exhaustSyncEvent()
-{
- if (isPostingSyncEvent) {
- sync(true);
- syncAlreadyHappened = true;
- }
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::sync(bool guiAlreadyLocked)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event");
-#endif
- if (!guiAlreadyLocked)
- lockInGui();
-
- for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin();
- it != m_rendered_windows.constEnd(); ++it) {
- QQuickWindowPrivate::get(it.key())->polishItems();
- }
-
- wake();
- wait();
-
- if (!guiAlreadyLocked)
- unlockInGui();
-}
-
-
-
-
-/*!
- Acquires the mutex for the GUI thread. The function uses the isGuiLocked
- variable to keep track of how many recursion levels the gui is locked with.
- We only actually acquire the mutex for the first level to avoid deadlocking
- ourselves.
- */
-
-void QQuickRenderThreadSingleContextWindowManager::lockInGui()
-{
- if (++isGuiLocked == 1)
- lock();
-
-#ifdef THREAD_DEBUG
- printf("GUI: acquired lock... level=%d\n", isGuiLocked);
-#endif
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::unlockInGui()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: releasing lock... level=%d\n", isGuiLocked);
-#endif
-
- if (--isGuiLocked == 0)
- unlock();
-}
-
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::animationStarted()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: animationStarted()\n");
-#endif
-
- if (!isRunning()) {
- animationTimer = startTimer(1000/60);
- return;
- }
-
- lockInGui();
-
- animationRunning = true;
-
- if (isRenderBlocked)
- wake();
-
- unlockInGui();
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::animationStopped()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: animationStopped()...\n");
-#endif
-
- if (!isRunning()) {
- killTimer(animationTimer);
- animationTimer = -1;
- return;
- }
-
- lockInGui();
- animationRunning = false;
- unlockInGui();
-}
-
-
-void QQuickRenderThreadSingleContextWindowManager::exposureChanged(QQuickWindow *window)
-{
- Q_UNUSED(window);
-#ifdef THREAD_DEBUG
- printf("GUI: exposure changed: %p\n", window);
-#endif
-
- if (window->isExposed())
- maybeUpdate(window);
-
-#ifdef THREAD_DEBUG
- printf("GUI: exposure changed done: %p\n", window);
-#endif
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::resize(QQuickWindow *window, const QSize &size)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Resize Event: %p = %dx%d\n", window, size.width(), size.height());
-#endif
-
- // If the rendering thread is not running we do not need to do anything.
- // Also if the window is being resized to an invalid size, it will be removed
- // by the windowVisibilityChanged slot as result of width/heightcChanged()
- if (!isRunning() || size.width() <= 0 || size.height() <= 0)
- return;
-
- lockInGui();
- exhaustSyncEvent();
-
- WindowData *windowData = m_rendered_windows.value(window);
- if (windowData) {
- windowData->windowSize = size;
- while (isRunning() && windowData->renderedSize != size && size.width() > 0 && size.height() > 0) {
- if (isRenderBlocked)
- wake();
- wait();
- }
- }
- unlockInGui();
-
-#ifdef THREAD_DEBUG
- printf("GUI: Resize done: %p\n", window);
-#endif
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::startRendering()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Starting Render Thread\n");
-#endif
- hasExited = false;
- shouldExit = false;
- isGuiLocked = 0;
- isPostingSyncEvent = false;
- syncAlreadyHappened = false;
- inSync = false;
-
- lockInGui();
- animationRunning = animDriver->isRunning();
- start(); // Start the render thread...
- wait();
- unlockInGui();
-
- // Animations will now be driven from the rendering thread.
- if (animationTimer >= 0) {
- killTimer(animationTimer);
- animationTimer = -1;
- }
-
-
-}
-
-
-
-void QQuickRenderThreadSingleContextWindowManager::stopRendering()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: stopping render thread\n");
-#endif
-
- lockInGui();
- exhaustSyncEvent();
- shouldExit = true;
-
- if (isRenderBlocked) {
-#ifdef THREAD_DEBUG
- printf("GUI: waking up render thread\n");
-#endif
- wake();
- }
-
- while (!hasExited) {
-#ifdef THREAD_DEBUG
- printf("GUI: waiting for render thread to have exited..\n");
-#endif
- wait();
- }
-
- unlockInGui();
-
-#ifdef THREAD_DEBUG
- printf("GUI: waiting for render thread to terminate..\n");
-#endif
- // Actually wait for the thread to terminate. Otherwise we can delete it
- // too early and crash.
- QThread::wait();
-
-#ifdef THREAD_DEBUG
- printf("GUI: thread has terminated and we're all good..\n");
-#endif
-
- // Activate timer to keep animations running
- if (animDriver->isRunning())
- animationTimer = startTimer(1000/60);
-}
-
-
-
-QImage QQuickRenderThreadSingleContextWindowManager::grab(QQuickWindow *window)
-{
- if (!isRunning())
- return QImage();
-
- if (QThread::currentThread() != qApp->thread()) {
- qWarning("QQuickWindow::grabFrameBuffer: can only be called from the GUI thread");
- return QImage();
- } else if (window->size().width() <= 0 || window->size().height() <= 0 ) {
- qWarning("QQuickWindow::grabFrameBuffer: Can't grab a Window with size %dx%d", window->size().width(), window->size().height());
- return QImage();
- }
-
-#ifdef THREAD_DEBUG
- printf("GUI: doing a pixelwise grab..\n");
-#endif
-
- lockInGui();
- exhaustSyncEvent();
-
- windowToGrab = window;
- while (isRunning() && windowToGrab) {
- if (isRenderBlocked)
- wake();
- wait();
- }
-
- QImage grabbed = grabContent;
- grabContent = QImage();
-
- unlockInGui();
-
- return grabbed;
-}
-
-
-void QQuickRenderThreadSingleContextWindowManager::handleDeferredUpdate()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: handling update to ourselves...\n");
-#endif
-
- isDeferredUpdatePosted = false;
-
- lockInGui();
- isExternalUpdatePending = true;
- if (isRenderBlocked)
- wake();
- unlockInGui();
-}
-
-void QQuickRenderThreadSingleContextWindowManager::maybeUpdate(QQuickWindow *)
-{
- Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || inSync,
- "QQuickWindow::update",
- "Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
-
- if (inSync) {
- isExternalUpdatePending = true;
-
- } else if (!isDeferredUpdatePosted) {
-#ifdef THREAD_DEBUG
- printf("GUI: posting update to ourselves...\n");
-#endif
- isDeferredUpdatePosted = true;
- QCoreApplication::postEvent(this, new QEvent(QEvent_DeferredUpdate));
- }
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/quick/items/qquickthreadedwindowmanager_p.h b/src/quick/items/qquickthreadedwindowmanager_p.h
deleted file mode 100644
index 76325e2d4f..0000000000
--- a/src/quick/items/qquickthreadedwindowmanager_p.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKTHREADEDWINDOWMANAGER_P_H
-#define QQUICKTHREADEDWINDOWMANAGER_P_H
-
-#include "qquickwindowmanager_p.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QMutex>
-#include <QtCore/QWaitCondition>
-#include <QtCore/private/qabstractanimation_p.h>
-
-#include <QtGui/QOpenGLContext>
-#include <QtQuick/private/qsgcontext_p.h>
-#include <private/qtquickglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickRenderThreadSingleContextWindowManager : public QThread, public QQuickWindowManager
-{
- Q_OBJECT
-public:
- QQuickRenderThreadSingleContextWindowManager()
- : sg(QSGContext::createDefaultContext())
- , gl(0)
- , animationTimer(-1)
- , isGuiLocked(0)
- , animationRunning(false)
- , isPostingSyncEvent(false)
- , isRenderBlocked(false)
- , isExternalUpdatePending(false)
- , syncAlreadyHappened(false)
- , inSync(false)
- , shouldExit(false)
- , hasExited(false)
- , isDeferredUpdatePosted(false)
- , windowToGrab(0)
- {
- sg->moveToThread(this);
-
- animDriver = sg->createAnimationDriver(this);
- animDriver->install();
- connect(animDriver, SIGNAL(started()), this, SLOT(animationStarted()));
- connect(animDriver, SIGNAL(stopped()), this, SLOT(animationStopped()));
- }
-
- QSGContext *sceneGraphContext() const { return sg; }
-
- void releaseResources() { }
-
- void show(QQuickWindow *window);
- void hide(QQuickWindow *window);
-
- void windowDestroyed(QQuickWindow *window);
-
- void exposureChanged(QQuickWindow *window);
- QImage grab(QQuickWindow *window);
- void resize(QQuickWindow *window, const QSize &size);
- void handleDeferredUpdate();
- void maybeUpdate(QQuickWindow *window);
- void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation
-
- void startRendering();
- void stopRendering();
-
- void exhaustSyncEvent();
- void sync(bool guiAlreadyLocked);
-
- void initialize();
-
- bool event(QEvent *);
-
- inline void lock() { mutex.lock(); }
- inline void unlock() { mutex.unlock(); }
- inline void wait() { condition.wait(&mutex); }
- inline void wake() { condition.wakeOne(); }
- void lockInGui();
- void unlockInGui();
-
- void run();
-
- QAnimationDriver *animationDriver() const { return animDriver; }
-
-public slots:
- void animationStarted();
- void animationStopped();
- void windowVisibilityChanged();
-
-private:
- void handleAddedWindows();
- void handleAddedWindow(QQuickWindow *window);
- void handleRemovedWindows(bool clearGLContext = true);
-
- QSGContext *sg;
- QOpenGLContext *gl;
- QAnimationDriver *animDriver;
- int animationTimer;
-
- QMutex mutex;
- QWaitCondition condition;
-
- int isGuiLocked;
- uint animationRunning: 1;
- uint isPostingSyncEvent : 1;
- uint isRenderBlocked : 1;
- uint isExternalUpdatePending : 1;
- uint syncAlreadyHappened : 1;
- uint inSync : 1;
- uint shouldExit : 1;
- uint hasExited : 1;
- uint isDeferredUpdatePosted : 1;
-
- QQuickWindow *windowToGrab;
- QImage grabContent;
-
- struct WindowData {
- QSize renderedSize;
- QSize windowSize;
- QSize viewportSize;
-
- uint sizeWasChanged : 1;
- uint isVisible : 1;
- uint isRenderable : 1;
- };
-
- QHash<QQuickWindow *, WindowData *> m_rendered_windows;
-
- struct WindowTracker {
- QQuickWindow *window;
- uint isVisible : 1;
- uint toBeRemoved : 1;
- };
-
- QList<WindowTracker> m_tracked_windows;
-
- QList<QQuickWindow *> m_removed_windows;
- QList<QQuickWindow *> m_added_windows;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKTHREADEDWINDOWMANAGER_P_H
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
index 8c3438c937..4181f5af79 100644
--- a/src/quick/items/qquicktranslate_p.h
+++ b/src/quick/items/qquicktranslate_p.h
@@ -46,8 +46,6 @@
#include <QtGui/qmatrix4x4.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickTranslatePrivate;
@@ -154,6 +152,4 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTranslate)
-QT_END_HEADER
-
#endif
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 29991357c9..65343cdc52 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -494,7 +494,7 @@ void QQuickViewPrivate::setRootObject(QObject *obj)
<< "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
<< endl
<< "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
- << "QQuickView class in the qtquick1 module." << endl;
+ << "QDeclarativeView class in the qtquick1 module." << endl;
delete obj;
root = 0;
}
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
index 10bad4c615..3e8883ddfb 100644
--- a/src/quick/items/qquickview.h
+++ b/src/quick/items/qquickview.h
@@ -46,8 +46,6 @@
#include <QtCore/qurl.h>
#include <QtQml/qqmldebug.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQmlEngine;
@@ -115,6 +113,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKVIEW_H
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 4b78d8b270..43b17e5bed 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -55,8 +55,6 @@
#include "qquickitemchangelistener_p.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQmlContext;
@@ -100,6 +98,4 @@ public:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QQUICKVIEW_P_H
diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp
deleted file mode 100644
index b57f4bbe76..0000000000
--- a/src/quick/items/qquickvisualadaptormodel.cpp
+++ /dev/null
@@ -1,977 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickvisualadaptormodel_p.h"
-#include "qquickvisualdatamodel_p_p.h"
-
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qqmlproperty_p.h>
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickVisualAdaptorModelEngineData : public QV8Engine::Deletable
-{
-public:
- enum
- {
- Index,
- ModelData,
- HasModelChildren,
- StringCount
- };
-
- QQuickVisualAdaptorModelEngineData(QV8Engine *engine);
- ~QQuickVisualAdaptorModelEngineData();
-
- v8::Local<v8::String> index() { return strings->Get(Index)->ToString(); }
- v8::Local<v8::String> modelData() { return strings->Get(ModelData)->ToString(); }
- v8::Local<v8::String> hasModelChildren() { return strings->Get(HasModelChildren)->ToString(); }
-
- v8::Persistent<v8::Function> constructorListItem;
- v8::Persistent<v8::Array> strings;
-};
-
-V8_DEFINE_EXTENSION(QQuickVisualAdaptorModelEngineData, engineData)
-
-static v8::Handle<v8::Value> get_index(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(data, "Not a valid VisualData object");
-
- return v8::Int32::New(data->index);
-}
-
-template <typename T, typename M> static void setModelDataType(QMetaObjectBuilder *builder, M *metaType)
-{
- builder->setFlags(QMetaObjectBuilder::DynamicMetaObject);
- builder->setClassName(T::staticMetaObject.className());
- builder->setSuperClass(&T::staticMetaObject);
- metaType->propertyOffset = T::staticMetaObject.propertyCount();
- metaType->signalOffset = T::staticMetaObject.methodCount();
-}
-
-static void addProperty(QMetaObjectBuilder *builder, int propertyId, const QByteArray &propertyName, const QByteArray &propertyType)
-{
- builder->addSignal("__" + QByteArray::number(propertyId) + "()");
- QMetaPropertyBuilder property = builder->addProperty(
- propertyName, propertyType, propertyId);
- property.setWritable(true);
-}
-
-class VDMModelDelegateDataType;
-
-class QQuickVDMCachedModelData : public QQuickVisualDataModelItem
-{
-public:
- QQuickVDMCachedModelData(
- QQuickVisualDataModelItemMetaType *metaType,
- VDMModelDelegateDataType *dataType,
- int index);
-
- int metaCall(QMetaObject::Call call, int id, void **arguments);
-
- virtual QVariant value(int role) const = 0;
- virtual void setValue(int role, const QVariant &value) = 0;
-
- void setValue(const QString &role, const QVariant &value);
- bool resolveIndex(const QQuickVisualAdaptorModel &model, int idx);
-
- static v8::Handle<v8::Value> get_property(v8::Local<v8::String>, const v8::AccessorInfo &info);
- static void set_property(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
-
- VDMModelDelegateDataType *type;
- QVector<QVariant> cachedData;
-};
-
-class VDMModelDelegateDataType
- : public QQmlRefCount
- , public QQuickVisualAdaptorModel::Accessors
- , public QAbstractDynamicMetaObject
-{
-public:
- VDMModelDelegateDataType(QQuickVisualAdaptorModel *model)
- : model(model)
- , metaObject(0)
- , propertyCache(0)
- , propertyOffset(0)
- , signalOffset(0)
- , hasModelData(false)
- {
- }
-
- ~VDMModelDelegateDataType()
- {
- if (propertyCache)
- propertyCache->release();
- free(metaObject);
-
- qPersistentDispose(constructor);
- }
-
- bool notify(
- const QQuickVisualAdaptorModel &,
- const QList<QQuickVisualDataModelItem *> &items,
- int index,
- int count,
- const QVector<int> &roles) const
- {
- bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
- if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
- QList<int> roleIds;
- foreach (const QByteArray &r, watchedRoles) {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(r);
- if (it != roleNames.end())
- roleIds << it.value();
- }
- const_cast<VDMModelDelegateDataType *>(this)->watchedRoleIds = roleIds;
- }
-
- QVector<int> signalIndexes;
- for (int i = 0; i < roles.count(); ++i) {
- const int role = roles.at(i);
- if (!changed && watchedRoleIds.contains(role))
- changed = true;
-
- int propertyId = propertyRoles.indexOf(role);
- if (propertyId != -1)
- signalIndexes.append(propertyId + signalOffset);
- }
- if (roles.isEmpty()) {
- for (int propertyId = 0; propertyId < propertyRoles.count(); ++propertyId)
- signalIndexes.append(propertyId + signalOffset);
- }
-
- for (int i = 0, c = items.count(); i < c; ++i) {
- QQuickVisualDataModelItem *item = items.at(i);
- const int idx = item->modelIndex();
- if (idx >= index && idx < index + count) {
- for (int i = 0; i < signalIndexes.count(); ++i)
- QMetaObject::activate(item, signalIndexes.at(i), 0);
- }
- }
- return changed;
- }
-
- void replaceWatchedRoles(
- QQuickVisualAdaptorModel &,
- const QList<QByteArray> &oldRoles,
- const QList<QByteArray> &newRoles) const
- {
- VDMModelDelegateDataType *dataType = const_cast<VDMModelDelegateDataType *>(this);
-
- dataType->watchedRoleIds.clear();
- foreach (const QByteArray &oldRole, oldRoles)
- dataType->watchedRoles.removeOne(oldRole);
- dataType->watchedRoles += newRoles;
- }
-
- void initializeConstructor(QQuickVisualAdaptorModelEngineData *const data)
- {
- constructor = qPersistentNew(v8::ObjectTemplate::New());
- constructor->SetHasExternalResource(true);
- constructor->SetAccessor(data->index(), get_index);
-
- typedef QHash<QByteArray, int>::const_iterator iterator;
- for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
- const int propertyId = propertyRoles.indexOf(it.value());
- const QByteArray &propertyName = it.key();
-
- constructor->SetAccessor(
- v8::String::New(propertyName.constData(), propertyName.length()),
- QQuickVDMCachedModelData::get_property,
- QQuickVDMCachedModelData::set_property,
- v8::Int32::New(propertyId));
- }
- }
-
- // QAbstractDynamicMetaObject
-
- void objectDestroyed(QObject *)
- {
- release();
- }
-
- int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments)
- {
- return static_cast<QQuickVDMCachedModelData *>(object)->metaCall(call, id, arguments);
- }
-
- v8::Persistent<v8::ObjectTemplate> constructor;
- QList<int> propertyRoles;
- QList<int> watchedRoleIds;
- QList<QByteArray> watchedRoles;
- QHash<QByteArray, int> roleNames;
- QQuickVisualAdaptorModel *model;
- QMetaObject *metaObject;
- QQmlPropertyCache *propertyCache;
- int propertyOffset;
- int signalOffset;
- bool hasModelData;
-};
-
-QQuickVDMCachedModelData::QQuickVDMCachedModelData(
- QQuickVisualDataModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index)
- : QQuickVisualDataModelItem(metaType, index)
- , type(dataType)
-{
- if (index == -1)
- cachedData.resize(type->hasModelData ? 1 : type->propertyRoles.count());
-
- QObjectPrivate::get(this)->metaObject = type;
-
- type->addref();
-
- QQmlData *qmldata = QQmlData::get(this, true);
- qmldata->propertyCache = dataType->propertyCache;
- qmldata->propertyCache->addref();
-}
-
-int QQuickVDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
-{
- if (call == QMetaObject::ReadProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- if (!cachedData.isEmpty()) {
- *static_cast<QVariant *>(arguments[0]) = cachedData.at(
- type->hasModelData ? 0 : propertyIndex);
- }
- } else if (*type->model) {
- *static_cast<QVariant *>(arguments[0]) = value(type->propertyRoles.at(propertyIndex));
- }
- return -1;
- } else if (call == QMetaObject::WriteProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- const QMetaObject *meta = metaObject();
- if (cachedData.count() > 1) {
- cachedData[propertyIndex] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, propertyIndex, 0);
- } else if (cachedData.count() == 1) {
- cachedData[0] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, 0, 0);
- QMetaObject::activate(this, meta, 1, 0);
- }
- } else if (*type->model) {
- setValue(type->propertyRoles.at(propertyIndex), *static_cast<QVariant *>(arguments[0]));
- }
- return -1;
- } else {
- return qt_metacall(call, id, arguments);
- }
-}
-
-void QQuickVDMCachedModelData::setValue(const QString &role, const QVariant &value)
-{
- QHash<QByteArray, int>::iterator it = type->roleNames.find(role.toUtf8());
- if (it != type->roleNames.end()) {
- for (int i = 0; i < type->propertyRoles.count(); ++i) {
- if (type->propertyRoles.at(i) == *it) {
- cachedData[i] = value;
- return;
- }
- }
- }
-}
-
-bool QQuickVDMCachedModelData::resolveIndex(const QQuickVisualAdaptorModel &, int idx)
-{
- if (index == -1) {
- Q_ASSERT(idx >= 0);
- index = idx;
- cachedData.clear();
- emit modelIndexChanged();
- const QMetaObject *meta = metaObject();
- const int propertyCount = type->propertyRoles.count();
- for (int i = 0; i < propertyCount; ++i)
- QMetaObject::activate(this, meta, i, 0);
- return true;
- } else {
- return false;
- }
-}
-
-v8::Handle<v8::Value> QQuickVDMCachedModelData::get_property(
- v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(data, "Not a valid VisualData object");
-
- QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
- const int propertyId = info.Data()->Int32Value();
- if (data->index == -1) {
- if (!modelData->cachedData.isEmpty()) {
- return data->engine->fromVariant(
- modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
- }
- } else if (*modelData->type->model) {
- return data->engine->fromVariant(
- modelData->value(modelData->type->propertyRoles.at(propertyId)));
- }
- return v8::Undefined();
-}
-
-void QQuickVDMCachedModelData::set_property(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE_SETTER(data, "Not a valid VisualData object");
-
- const int propertyId = info.Data()->Int32Value();
- if (data->index == -1) {
- QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
- if (!modelData->cachedData.isEmpty()) {
- if (modelData->cachedData.count() > 1) {
- modelData->cachedData[propertyId] = data->engine->toVariant(value, QVariant::Invalid);
- QMetaObject::activate(data, data->metaObject(), propertyId, 0);
- } else if (modelData->cachedData.count() == 1) {
- modelData->cachedData[0] = data->engine->toVariant(value, QVariant::Invalid);
- QMetaObject::activate(data, data->metaObject(), 0, 0);
- QMetaObject::activate(data, data->metaObject(), 1, 0);
- }
- }
- }
-}
-
-//-----------------------------------------------------------------
-// QAbstractItemModel
-//-----------------------------------------------------------------
-
-class QQuickVDMAbstractItemModelData : public QQuickVDMCachedModelData
-{
- Q_OBJECT
- Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
-public:
- QQuickVDMAbstractItemModelData(
- QQuickVisualDataModelItemMetaType *metaType,
- VDMModelDelegateDataType *dataType,
- int index)
- : QQuickVDMCachedModelData(metaType, dataType, index)
- {
- }
-
- bool hasModelChildren() const
- {
- if (index >= 0 && *type->model) {
- const QAbstractItemModel * const model = type->model->aim();
- return model->hasChildren(model->index(index, 0, type->model->rootIndex));
- } else {
- return false;
- }
- }
-
- QVariant value(int role) const
- {
- return type->model->aim()->index(index, 0, type->model->rootIndex).data(role);
- }
-
- void setValue(int role, const QVariant &value)
- {
- type->model->aim()->setData(
- type->model->aim()->index(index, 0, type->model->rootIndex), value, role);
- }
-
- v8::Handle<v8::Value> get()
- {
- if (type->constructor.IsEmpty()) {
- QQuickVisualAdaptorModelEngineData * const data = engineData(engine);
- v8::HandleScope handleScope;
- v8::Context::Scope contextScope(engine->context());
- type->initializeConstructor(data);
- type->constructor->SetAccessor(data->hasModelChildren(), get_hasModelChildren);
- }
- v8::Local<v8::Object> data = type->constructor->NewInstance();
- data->SetExternalResource(this);
- ++scriptRef;
- return data;
- }
-
- static v8::Handle<v8::Value> get_hasModelChildren(v8::Local<v8::String>, const v8::AccessorInfo &info)
- {
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(data, "Not a valid VisualData object");
-
- const QQuickVisualAdaptorModel *const model = static_cast<QQuickVDMCachedModelData *>(data)->type->model;
- if (data->index >= 0 && *model) {
- const QAbstractItemModel * const aim = model->aim();
- return v8::Boolean::New(aim->hasChildren(aim->index(data->index, 0, model->rootIndex)));
- } else {
- return v8::Boolean::New(false);
- }
- }
-};
-
-class VDMAbstractItemModelDataType : public VDMModelDelegateDataType
-{
-public:
- VDMAbstractItemModelDataType(QQuickVisualAdaptorModel *model)
- : VDMModelDelegateDataType(model)
- {
- }
-
- int count(const QQuickVisualAdaptorModel &model) const
- {
- return model.aim()->rowCount(model.rootIndex);
- }
-
- void cleanup(QQuickVisualAdaptorModel &model, QQuickVisualDataModel *vdm) const
- {
- QAbstractItemModel * const aim = model.aim();
- if (aim && vdm) {
- QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- vdm, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(aim, SIGNAL(modelReset()),
- vdm, SLOT(_q_modelReset()));
- QObject::disconnect(aim, SIGNAL(layoutChanged()),
- vdm, SLOT(_q_layoutChanged()));
- }
-
- const_cast<VDMAbstractItemModelDataType *>(this)->release();
- }
-
- QVariant value(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
- {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
- if (it != roleNames.end()) {
- return model.aim()->index(index, 0, model.rootIndex).data(*it);
- } else if (role == QLatin1String("hasModelChildren")) {
- return QVariant(model.aim()->hasChildren(model.aim()->index(index, 0, model.rootIndex)));
- } else {
- return QVariant();
- }
- }
-
- QVariant parentModelIndex(const QQuickVisualAdaptorModel &model) const
- {
- return model
- ? QVariant::fromValue(model.aim()->parent(model.rootIndex))
- : QVariant();
- }
-
- QVariant modelIndex(const QQuickVisualAdaptorModel &model, int index) const
- {
- return model
- ? QVariant::fromValue(model.aim()->index(index, 0, model.rootIndex))
- : QVariant();
- }
-
- bool canFetchMore(const QQuickVisualAdaptorModel &model) const
- {
- return model && model.aim()->canFetchMore(model.rootIndex);
- }
-
- void fetchMore(QQuickVisualAdaptorModel &model) const
- {
- if (model)
- model.aim()->fetchMore(model.rootIndex);
- }
-
- QQuickVisualDataModelItem *createItem(
- QQuickVisualAdaptorModel &model,
- QQuickVisualDataModelItemMetaType *metaType,
- QQmlEngine *engine,
- int index) const
- {
- VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model, engine);
- return new QQuickVDMAbstractItemModelData(metaType, dataType, index);
- }
-
- void initializeMetaType(QQuickVisualAdaptorModel &model, QQmlEngine *engine)
- {
- QMetaObjectBuilder builder;
- setModelDataType<QQuickVDMAbstractItemModelData>(&builder, this);
-
- const QByteArray propertyType = QByteArrayLiteral("QVariant");
- const QHash<int, QByteArray> names = model.aim()->roleNames();
- for (QHash<int, QByteArray>::const_iterator it = names.begin(); it != names.end(); ++it) {
- const int propertyId = propertyRoles.count();
- propertyRoles.append(it.key());
- roleNames.insert(it.value(), it.key());
- addProperty(&builder, propertyId, it.value(), propertyType);
- }
- if (propertyRoles.count() == 1) {
- hasModelData = true;
- const int role = names.begin().key();
- const QByteArray propertyName = QByteArrayLiteral("modelData");
-
- propertyRoles.append(role);
- roleNames.insert(propertyName, role);
- addProperty(&builder, 1, propertyName, propertyType);
- }
-
- metaObject = builder.toMetaObject();
- *static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = new QQmlPropertyCache(engine, metaObject);
- }
-};
-
-//-----------------------------------------------------------------
-// QQuickListAccessor
-//-----------------------------------------------------------------
-
-class QQuickVDMListAccessorData : public QQuickVisualDataModelItem
-{
- Q_OBJECT
- Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
-public:
- QQuickVDMListAccessorData(QQuickVisualDataModelItemMetaType *metaType, int index, const QVariant &value)
- : QQuickVisualDataModelItem(metaType, index)
- , cachedData(value)
- {
- }
-
- QVariant modelData() const
- {
- return cachedData;
- }
-
- void setModelData(const QVariant &data)
- {
- if (index == -1 && data != cachedData) {
- cachedData = data;
- emit modelDataChanged();
- }
- }
-
- static v8::Handle<v8::Value> get_modelData(v8::Local<v8::String>, const v8::AccessorInfo &info)
- {
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(data, "Not a valid VisualData object");
-
- return data->engine->fromVariant(static_cast<QQuickVDMListAccessorData *>(data)->cachedData);
- }
-
- static void set_modelData(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
- {
- QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE_SETTER(data, "Not a valid VisualData object");
-
- static_cast<QQuickVDMListAccessorData *>(data)->setModelData(
- data->engine->toVariant(value, QVariant::Invalid));
- }
-
- v8::Handle<v8::Value> get()
- {
- v8::Local<v8::Object> data = engineData(engine)->constructorListItem->NewInstance();
- data->SetExternalResource(this);
- ++scriptRef;
- return data;
- }
-
- void setValue(const QString &role, const QVariant &value)
- {
- if (role == QLatin1String("modelData"))
- cachedData = value;
- }
-
- bool resolveIndex(const QQuickVisualAdaptorModel &model, int idx)
- {
- if (index == -1) {
- index = idx;
- cachedData = model.list.at(idx);
- emit modelIndexChanged();
- emit modelDataChanged();
- return true;
- } else {
- return false;
- }
- }
-
-
-Q_SIGNALS:
- void modelDataChanged();
-
-private:
- QVariant cachedData;
-};
-
-
-class VDMListDelegateDataType : public QQuickVisualAdaptorModel::Accessors
-{
-public:
- inline VDMListDelegateDataType() {}
-
- int count(const QQuickVisualAdaptorModel &model) const
- {
- return model.list.count();
- }
-
- QVariant value(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
- {
- return role == QLatin1String("modelData")
- ? model.list.at(index)
- : QVariant();
- }
-
- QQuickVisualDataModelItem *createItem(
- QQuickVisualAdaptorModel &model,
- QQuickVisualDataModelItemMetaType *metaType,
- QQmlEngine *,
- int index) const
- {
- return new QQuickVDMListAccessorData(
- metaType,
- index,
- index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
- }
-};
-
-//-----------------------------------------------------------------
-// QObject
-//-----------------------------------------------------------------
-
-class VDMObjectDelegateDataType;
-class QQuickVDMObjectData : public QQuickVisualDataModelItem, public QQuickVisualAdaptorModelProxyInterface
-{
- Q_OBJECT
- Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
- Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
-public:
- QQuickVDMObjectData(
- QQuickVisualDataModelItemMetaType *metaType,
- VDMObjectDelegateDataType *dataType,
- int index,
- QObject *object);
-
- QObject *modelData() const { return object; }
- QObject *proxiedObject() { return object; }
-
- QQmlGuard<QObject> object;
-};
-
-class VDMObjectDelegateDataType : public QQmlRefCount, public QQuickVisualAdaptorModel::Accessors
-{
-public:
- QMetaObject *metaObject;
- int propertyOffset;
- int signalOffset;
- bool shared;
- QMetaObjectBuilder builder;
-
- VDMObjectDelegateDataType()
- : metaObject(0)
- , propertyOffset(0)
- , signalOffset(0)
- , shared(true)
- {
- }
-
- VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
- : QQmlRefCount()
- , QQuickVisualAdaptorModel::Accessors()
- , metaObject(0)
- , propertyOffset(type.propertyOffset)
- , signalOffset(type.signalOffset)
- , shared(false)
- , builder(type.metaObject, QMetaObjectBuilder::Properties
- | QMetaObjectBuilder::Signals
- | QMetaObjectBuilder::SuperClass
- | QMetaObjectBuilder::ClassName)
- {
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- }
-
- ~VDMObjectDelegateDataType()
- {
- free(metaObject);
- }
-
- int count(const QQuickVisualAdaptorModel &model) const
- {
- return model.list.count();
- }
-
- QVariant value(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
- {
- if (QObject *object = model.list.at(index).value<QObject *>())
- return object->property(role.toUtf8());
- return QVariant();
- }
-
- QQuickVisualDataModelItem *createItem(
- QQuickVisualAdaptorModel &model,
- QQuickVisualDataModelItemMetaType *metaType,
- QQmlEngine *,
- int index) const
- {
- VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model);
- return index >= 0 && index < model.list.count()
- ? new QQuickVDMObjectData(metaType, dataType, index, qvariant_cast<QObject *>(model.list.at(index)))
- : 0;
- }
-
- void initializeMetaType(QQuickVisualAdaptorModel &)
- {
- setModelDataType<QQuickVDMObjectData>(&builder, this);
-
- metaObject = builder.toMetaObject();
- }
-
- void cleanup(QQuickVisualAdaptorModel &, QQuickVisualDataModel *) const
- {
- const_cast<VDMObjectDelegateDataType *>(this)->release();
- }
-};
-
-class QQuickVDMObjectDataMetaObject : public QAbstractDynamicMetaObject
-{
-public:
- QQuickVDMObjectDataMetaObject(QQuickVDMObjectData *data, VDMObjectDelegateDataType *type)
- : m_data(data)
- , m_type(type)
- {
- QObjectPrivate *op = QObjectPrivate::get(m_data);
- *static_cast<QMetaObject *>(this) = *type->metaObject;
- op->metaObject = this;
- m_type->addref();
- }
-
- ~QQuickVDMObjectDataMetaObject()
- {
- m_type->release();
- }
-
- int metaCall(QMetaObject::Call call, int id, void **arguments)
- {
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
- if (id >= m_type->propertyOffset
- && (call == QMetaObject::ReadProperty
- || call == QMetaObject::WriteProperty
- || call == QMetaObject::ResetProperty)) {
- if (m_data->object)
- QMetaObject::metacall(m_data->object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
- return -1;
- } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
- QMetaObject::activate(m_data, this, id - m_type->signalOffset, 0);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-
- int createProperty(const char *name, const char *)
- {
- if (!m_data->object)
- return -1;
- const QMetaObject *metaObject = m_data->object->metaObject();
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
-
- const int previousPropertyCount = propertyCount() - propertyOffset();
- int propertyIndex = metaObject->indexOfProperty(name);
- if (propertyIndex == -1)
- return -1;
- if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
-
- if (m_type->shared) {
- VDMObjectDelegateDataType *type = m_type;
- m_type = new VDMObjectDelegateDataType(*m_type);
- type->release();
- }
-
- const int previousMethodCount = methodCount();
- int notifierId = previousMethodCount - methodOffset();
- for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
- QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
- QMetaPropertyBuilder propertyBuilder;
- if (property.hasNotifySignal()) {
- m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
- ++notifierId;
- } else {
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
- }
- propertyBuilder.setWritable(property.isWritable());
- propertyBuilder.setResettable(property.isResettable());
- propertyBuilder.setConstant(property.isConstant());
- }
-
- if (m_type->metaObject)
- free(m_type->metaObject);
- m_type->metaObject = m_type->builder.toMetaObject();
- *static_cast<QMetaObject *>(this) = *m_type->metaObject;
-
- notifierId = previousMethodCount;
- for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
- QMetaProperty property = metaObject->property(i + objectPropertyOffset);
- if (property.hasNotifySignal()) {
- QQmlPropertyPrivate::connect(
- m_data->object, property.notifySignalIndex(), m_data, notifierId);
- ++notifierId;
- }
- }
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
- }
-
- QQuickVDMObjectData *m_data;
- VDMObjectDelegateDataType *m_type;
-};
-
-QQuickVDMObjectData::QQuickVDMObjectData(
- QQuickVisualDataModelItemMetaType *metaType,
- VDMObjectDelegateDataType *dataType,
- int index,
- QObject *object)
- : QQuickVisualDataModelItem(metaType, index)
- , object(object)
-{
- new QQuickVDMObjectDataMetaObject(this, dataType);
-}
-
-//-----------------------------------------------------------------
-// QQuickVisualAdaptorModel
-//-----------------------------------------------------------------
-
-static const QQuickVisualAdaptorModel::Accessors qt_vdm_null_accessors;
-static const VDMListDelegateDataType qt_vdm_list_accessors;
-
-QQuickVisualAdaptorModel::Accessors::~Accessors()
-{
-}
-
-QQuickVisualAdaptorModel::QQuickVisualAdaptorModel()
- : accessors(&qt_vdm_null_accessors)
-{
-}
-
-QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
-{
- accessors->cleanup(*this);
-}
-
-void QQuickVisualAdaptorModel::setModel(const QVariant &variant, QQuickVisualDataModel *vdm, QQmlEngine *engine)
-{
- accessors->cleanup(*this, vdm);
-
- list.setList(variant, engine);
-
- if (QObject *object = qvariant_cast<QObject *>(variant)) {
- setObject(object);
- if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(object)) {
- accessors = new VDMAbstractItemModelDataType(this);
-
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- vdm, QQuickVisualDataModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- vdm, QQuickVisualDataModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- vdm, QQuickVisualDataModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- vdm, QQuickVisualDataModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- vdm, QQuickVisualDataModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
- vdm, QQuickVisualDataModel, SLOT(_q_modelReset()));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged()),
- vdm, QQuickVisualDataModel, SLOT(_q_layoutChanged()));
- } else {
- accessors = new VDMObjectDelegateDataType;
- }
- } else if (list.type() == QQuickListAccessor::ListProperty) {
- setObject(static_cast<const QQmlListReference *>(variant.constData())->object());
- accessors = new VDMObjectDelegateDataType;
- } else if (list.type() != QQuickListAccessor::Invalid) {
- Q_ASSERT(list.type() != QQuickListAccessor::Instance); // Should have cast to QObject.
- setObject(0);
- accessors = &qt_vdm_list_accessors;
- } else {
- setObject(0);
- accessors = &qt_vdm_null_accessors;
- }
-}
-
-void QQuickVisualAdaptorModel::invalidateModel(QQuickVisualDataModel *vdm)
-{
- accessors->cleanup(*this, vdm);
- accessors = &qt_vdm_null_accessors;
- // Don't clear the model object as we still need the guard to clear the list variant if the
- // object is destroyed.
-}
-
-bool QQuickVisualAdaptorModel::isValid() const
-{
- return accessors != &qt_vdm_null_accessors;
-}
-
-void QQuickVisualAdaptorModel::objectDestroyed(QObject *)
-{
- setModel(QVariant(), 0, 0);
-}
-
-QQuickVisualAdaptorModelEngineData::QQuickVisualAdaptorModelEngineData(QV8Engine *)
-{
- strings = qPersistentNew(v8::Array::New(StringCount));
- strings->Set(Index, v8::String::New("index"));
- strings->Set(ModelData, v8::String::New("modelData"));
- strings->Set(HasModelChildren, v8::String::New("hasModelChildren"));
-
- v8::Local<v8::FunctionTemplate> listItem = v8::FunctionTemplate::New();
- listItem->InstanceTemplate()->SetHasExternalResource(true);
- listItem->InstanceTemplate()->SetAccessor(index(), get_index);
- listItem->InstanceTemplate()->SetAccessor(
- modelData(),
- QQuickVDMListAccessorData::get_modelData,
- QQuickVDMListAccessorData::set_modelData);
- constructorListItem = qPersistentNew(listItem->GetFunction());
-}
-
-QQuickVisualAdaptorModelEngineData::~QQuickVisualAdaptorModelEngineData()
-{
- qPersistentDispose(constructorListItem);
- qPersistentDispose(strings);
-}
-
-QT_END_NAMESPACE
-
-#include <qquickvisualadaptormodel.moc>
diff --git a/src/quick/items/qquickvisualadaptormodel_p.h b/src/quick/items/qquickvisualadaptormodel_p.h
deleted file mode 100644
index 40890f8560..0000000000
--- a/src/quick/items/qquickvisualadaptormodel_p.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKVISUALADAPTORMODEL_P_H
-#define QQUICKVISUALADAPTORMODEL_P_H
-
-#include <QtCore/qabstractitemmodel.h>
-
-#include "private/qquicklistaccessor_p.h"
-
-#include <private/qqmlguard_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QQmlEngine;
-
-class QQuickVisualDataModel;
-class QQuickVisualDataModelItem;
-class QQuickVisualDataModelItemMetaType;
-
-class QQuickVisualAdaptorModel : public QQmlGuard<QObject>
-{
-public:
- class Accessors
- {
- public:
- inline Accessors() {}
- virtual ~Accessors();
- virtual int count(const QQuickVisualAdaptorModel &) const { return 0; }
- virtual void cleanup(QQuickVisualAdaptorModel &, QQuickVisualDataModel * = 0) const {}
-
- virtual QVariant value(const QQuickVisualAdaptorModel &, int, const QString &) const {
- return QVariant(); }
-
- virtual QQuickVisualDataModelItem *createItem(
- QQuickVisualAdaptorModel &,
- QQuickVisualDataModelItemMetaType *,
- QQmlEngine *,
- int) const { return 0; }
-
- virtual bool notify(
- const QQuickVisualAdaptorModel &,
- const QList<QQuickVisualDataModelItem *> &,
- int,
- int,
- const QVector<int> &) const { return false; }
- virtual void replaceWatchedRoles(
- QQuickVisualAdaptorModel &,
- const QList<QByteArray> &,
- const QList<QByteArray> &) const {}
- virtual QVariant parentModelIndex(const QQuickVisualAdaptorModel &) const {
- return QVariant(); }
- virtual QVariant modelIndex(const QQuickVisualAdaptorModel &, int) const {
- return QVariant(); }
- virtual bool canFetchMore(const QQuickVisualAdaptorModel &) const { return false; }
- virtual void fetchMore(QQuickVisualAdaptorModel &) const {}
- };
-
- const Accessors *accessors;
- QPersistentModelIndex rootIndex;
- QQuickListAccessor list;
-
- QQuickVisualAdaptorModel();
- ~QQuickVisualAdaptorModel();
-
- inline QVariant model() const { return list.list(); }
- void setModel(const QVariant &variant, QQuickVisualDataModel *vdm, QQmlEngine *engine);
- void invalidateModel(QQuickVisualDataModel *vdm);
-
- bool isValid() const;
-
- inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); }
- inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); }
-
- inline int count() const { return qMax(0, accessors->count(*this)); }
- inline QVariant value(int index, const QString &role) const {
- return accessors->value(*this, index, role); }
- inline QQuickVisualDataModelItem *createItem(QQuickVisualDataModelItemMetaType *metaType, QQmlEngine *engine, int index) {
- return accessors->createItem(*this, metaType, engine, index); }
- inline bool hasProxyObject() const {
- return list.type() == QQuickListAccessor::Instance || list.type() == QQuickListAccessor::ListProperty; }
-
- inline bool notify(
- const QList<QQuickVisualDataModelItem *> &items,
- int index,
- int count,
- const QVector<int> &roles) const {
- return accessors->notify(*this, items, index, count, roles); }
- inline void replaceWatchedRoles(
- const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles) {
- accessors->replaceWatchedRoles(*this, oldRoles, newRoles); }
-
- inline QVariant modelIndex(int index) const { return accessors->modelIndex(*this, index); }
- inline QVariant parentModelIndex() const { return accessors->parentModelIndex(*this); }
- inline bool canFetchMore() const { return accessors->canFetchMore(*this); }
- inline void fetchMore() { return accessors->fetchMore(*this); }
-
-protected:
- void objectDestroyed(QObject *);
-};
-
-class QQuickVisualAdaptorModelProxyInterface
-{
-public:
- virtual ~QQuickVisualAdaptorModelProxyInterface() {}
-
- virtual QObject *proxiedObject() = 0;
-};
-
-#define QQuickVisualAdaptorModelProxyInterface_iid "org.qt-project.Qt.QQuickVisualAdaptorModelProxyInterface"
-
-Q_DECLARE_INTERFACE(QQuickVisualAdaptorModelProxyInterface, QQuickVisualAdaptorModelProxyInterface_iid)
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
deleted file mode 100644
index d2e50e8b8a..0000000000
--- a/src/quick/items/qquickvisualdatamodel.cpp
+++ /dev/null
@@ -1,3173 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickvisualdatamodel_p_p.h"
-#include "qquickitem.h"
-
-#include <QtQml/qqmlinfo.h>
-
-#include <private/qquickpackage_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qquickvisualadaptormodel_p.h>
-#include <private/qquickchangeset_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlcomponent_p.h>
-#include <private/qqmlincubator_p.h>
-#include <private/qqmlcompiler_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickVisualDataModelEngineData : public QV8Engine::Deletable
-{
-public:
- enum
- {
- Model,
- Groups,
- IsUnresolved,
- ItemsIndex,
- PersistedItemsIndex,
- InItems,
- InPersistedItems,
- StringCount
- };
-
- QQuickVisualDataModelEngineData(QV8Engine *engine);
- ~QQuickVisualDataModelEngineData();
-
- v8::Local<v8::Object> array(
- QV8Engine *engine, const QVector<QQuickChangeSet::Remove> &changes);
- v8::Local<v8::Object> array(
- QV8Engine *engine, const QVector<QQuickChangeSet::Insert> &changes);
- v8::Local<v8::Object> array(
- QV8Engine *engine, const QVector<QQuickChangeSet::Change> &changes);
-
-
- inline v8::Local<v8::String> model() { return strings->Get(Model)->ToString(); }
- inline v8::Local<v8::String> groups() { return strings->Get(Groups)->ToString(); }
- inline v8::Local<v8::String> isUnresolved() { return strings->Get(IsUnresolved)->ToString(); }
- inline v8::Local<v8::String> itemsIndex() { return strings->Get(ItemsIndex)->ToString(); }
- inline v8::Local<v8::String> persistedItemsIndex() { return strings->Get(PersistedItemsIndex)->ToString(); }
- inline v8::Local<v8::String> inItems() { return strings->Get(InItems)->ToString(); }
- inline v8::Local<v8::String> inPersistedItems() { return strings->Get(InPersistedItems)->ToString(); }
-
- v8::Persistent<v8::Array> strings;
- v8::Persistent<v8::Function> constructorChange;
- v8::Persistent<v8::Function> constructorChangeArray;
-};
-
-V8_DEFINE_EXTENSION(QQuickVisualDataModelEngineData, engineData)
-
-
-void QQuickVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
-{
- prop.setWritable(false);
-}
-
-QVariant QQuickVisualDataModelPartsMetaObject::initialValue(int id)
-{
- QQuickVisualDataModelParts *parts = static_cast<QQuickVisualDataModelParts *>(object());
- QQuickVisualPartsModel *m = new QQuickVisualPartsModel(
- parts->model, QString::fromUtf8(name(id)), parts);
- parts->models.append(m);
- return QVariant::fromValue(static_cast<QObject *>(m));
-}
-
-QQuickVisualDataModelParts::QQuickVisualDataModelParts(QQuickVisualDataModel *parent)
-: QObject(parent), model(parent)
-{
- new QQuickVisualDataModelPartsMetaObject(this);
-}
-
-//---------------------------------------------------------------------------
-
-/*!
- \qmltype VisualDataModel
- \instantiates QQuickVisualDataModel
- \inqmlmodule QtQuick 2
- \ingroup qtquick-models
- \brief Encapsulates a model and delegate
-
- The VisualDataModel type encapsulates a model and the delegate that will
- be instantiated for items in the model.
-
- It is usually not necessary to create a VisualDataModel.
- However, it can be useful for manipulating and accessing the \l modelIndex
- when a QAbstractItemModel subclass is used as the
- model. Also, VisualDataModel is used together with \l Package to
- provide delegates to multiple views, and with VisualDataGroup to sort and filter
- delegate items.
-
- The example below illustrates using a VisualDataModel with a ListView.
-
- \snippet qml/visualdatamodel.qml 0
-*/
-
-QQuickVisualDataModelPrivate::QQuickVisualDataModelPrivate(QQmlContext *ctxt)
- : m_delegate(0)
- , m_cacheMetaType(0)
- , m_context(ctxt)
- , m_parts(0)
- , m_filterGroup(QStringLiteral("items"))
- , m_count(0)
- , m_groupCount(Compositor::MinimumGroupCount)
- , m_compositorGroup(Compositor::Cache)
- , m_complete(false)
- , m_delegateValidated(false)
- , m_reset(false)
- , m_transaction(false)
- , m_incubatorCleanupScheduled(false)
- , m_cacheItems(0)
- , m_items(0)
- , m_persistedItems(0)
-{
-}
-
-QQuickVisualDataModelPrivate::~QQuickVisualDataModelPrivate()
-{
- qDeleteAll(m_finishedIncubating);
-
- if (m_cacheMetaType)
- m_cacheMetaType->release();
-}
-
-void QQuickVisualDataModelPrivate::init()
-{
- Q_Q(QQuickVisualDataModel);
- m_compositor.setRemoveGroups(Compositor::GroupMask & ~Compositor::PersistedFlag);
-
- m_items = new QQuickVisualDataGroup(QStringLiteral("items"), q, Compositor::Default, q);
- m_items->setDefaultInclude(true);
- m_persistedItems = new QQuickVisualDataGroup(QStringLiteral("persistedItems"), q, Compositor::Persisted, q);
- QQuickVisualDataGroupPrivate::get(m_items)->emitters.insert(this);
-}
-
-QQuickVisualDataModel::QQuickVisualDataModel()
-: QQuickVisualModel(*(new QQuickVisualDataModelPrivate(0)))
-{
- Q_D(QQuickVisualDataModel);
- d->init();
-}
-
-QQuickVisualDataModel::QQuickVisualDataModel(QQmlContext *ctxt, QObject *parent)
-: QQuickVisualModel(*(new QQuickVisualDataModelPrivate(ctxt)), parent)
-{
- Q_D(QQuickVisualDataModel);
- d->init();
-}
-
-QQuickVisualDataModel::~QQuickVisualDataModel()
-{
- Q_D(QQuickVisualDataModel);
-
- foreach (QQuickVisualDataModelItem *cacheItem, d->m_cache) {
- if (cacheItem->object) {
- delete cacheItem->object;
-
- cacheItem->object = 0;
- cacheItem->contextData->destroy();
- cacheItem->contextData = 0;
- cacheItem->scriptRef -= 1;
- }
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
- cacheItem->objectRef = 0;
- if (!cacheItem->isReferenced())
- delete cacheItem;
- }
-}
-
-
-void QQuickVisualDataModel::classBegin()
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_context)
- d->m_context = qmlContext(this);
-}
-
-void QQuickVisualDataModel::componentComplete()
-{
- Q_D(QQuickVisualDataModel);
- d->m_complete = true;
-
- int defaultGroups = 0;
- QStringList groupNames;
- groupNames.append(QStringLiteral("items"));
- groupNames.append(QStringLiteral("persistedItems"));
- if (QQuickVisualDataGroupPrivate::get(d->m_items)->defaultInclude)
- defaultGroups |= Compositor::DefaultFlag;
- if (QQuickVisualDataGroupPrivate::get(d->m_persistedItems)->defaultInclude)
- defaultGroups |= Compositor::PersistedFlag;
- for (int i = Compositor::MinimumGroupCount; i < d->m_groupCount; ++i) {
- QString name = d->m_groups[i]->name();
- if (name.isEmpty()) {
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else if (name.at(0).isUpper()) {
- qmlInfo(d->m_groups[i]) << QQuickVisualDataGroup::tr("Group names must start with a lower case letter");
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else {
- groupNames.append(name);
-
- QQuickVisualDataGroupPrivate *group = QQuickVisualDataGroupPrivate::get(d->m_groups[i]);
- group->setModel(this, Compositor::Group(i));
- if (group->defaultInclude)
- defaultGroups |= (1 << i);
- }
- }
-
- d->m_cacheMetaType = new QQuickVisualDataModelItemMetaType(
- QQmlEnginePrivate::getV8Engine(d->m_context->engine()), this, groupNames);
-
- d->m_compositor.setGroupCount(d->m_groupCount);
- d->m_compositor.setDefaultGroups(defaultGroups);
- d->updateFilterGroup();
-
- while (!d->m_pendingParts.isEmpty())
- static_cast<QQuickVisualPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
-
- QVector<Compositor::Insert> inserts;
- d->m_count = d->m_adaptorModel.count();
- d->m_compositor.append(
- &d->m_adaptorModel,
- 0,
- d->m_count,
- defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
- &inserts);
- d->itemsInserted(inserts);
- d->emitChanges();
-
- if (d->m_adaptorModel.canFetchMore())
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
-}
-
-/*!
- \qmlproperty model QtQuick2::VisualDataModel::model
- This property holds the model providing data for the VisualDataModel.
-
- The model provides a set of data that is used to create the items
- for a view. For large or dynamic datasets the model is usually
- provided by a C++ model object. The C++ model object must be a \l
- {QAbstractItemModel} subclass or a simple list.
-
- Models can also be created directly in QML, using a \l{ListModel} or
- \l{XmlListModel}.
-
- \sa {qml-data-models}{Data Models}
-*/
-QVariant QQuickVisualDataModel::model() const
-{
- Q_D(const QQuickVisualDataModel);
- return d->m_adaptorModel.model();
-}
-
-void QQuickVisualDataModel::setModel(const QVariant &model)
-{
- Q_D(QQuickVisualDataModel);
-
- if (d->m_complete)
- _q_itemsRemoved(0, d->m_count);
-
- d->m_adaptorModel.setModel(model, this, d->m_context->engine());
- d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
- for (int i = 0; d->m_parts && i < d->m_parts->models.count(); ++i) {
- d->m_adaptorModel.replaceWatchedRoles(
- QList<QByteArray>(), d->m_parts->models.at(i)->watchedRoles());
- }
-
- if (d->m_complete) {
- _q_itemsInserted(0, d->m_adaptorModel.count());
- if (d->m_adaptorModel.canFetchMore())
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
-}
-
-/*!
- \qmlproperty Component QtQuick2::VisualDataModel::delegate
-
- The delegate provides a template defining each item instantiated by a view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qml-data-models}{Data Model}.
-*/
-QQmlComponent *QQuickVisualDataModel::delegate() const
-{
- Q_D(const QQuickVisualDataModel);
- return d->m_delegate;
-}
-
-void QQuickVisualDataModel::setDelegate(QQmlComponent *delegate)
-{
- Q_D(QQuickVisualDataModel);
- if (d->m_transaction) {
- qmlInfo(this) << tr("The delegate of a VisualDataModel cannot be changed within onUpdated.");
- return;
- }
- bool wasValid = d->m_delegate != 0;
- d->m_delegate = delegate;
- d->m_delegateValidated = false;
- if (wasValid && d->m_complete) {
- for (int i = 1; i < d->m_groupCount; ++i) {
- QQuickVisualDataGroupPrivate::get(d->m_groups[i])->changeSet.remove(
- 0, d->m_compositor.count(Compositor::Group(i)));
- }
- }
- if (d->m_complete && d->m_delegate) {
- for (int i = 1; i < d->m_groupCount; ++i) {
- QQuickVisualDataGroupPrivate::get(d->m_groups[i])->changeSet.insert(
- 0, d->m_compositor.count(Compositor::Group(i)));
- }
- }
- d->emitChanges();
-}
-
-/*!
- \qmlproperty QModelIndex QtQuick2::VisualDataModel::rootIndex
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. \c rootIndex allows the children of
- any node in a QAbstractItemModel to be provided by this model.
-
- This property only affects models of type QAbstractItemModel that
- are hierarchical (e.g, a tree model).
-
- For example, here is a simple interactive file system browser.
- When a directory name is clicked, the view's \c rootIndex is set to the
- QModelIndex node of the clicked directory, thus updating the view to show
- the new directory's contents.
-
- \c main.cpp:
- \snippet qml/visualdatamodel_rootindex/main.cpp 0
-
- \c view.qml:
- \snippet qml/visualdatamodel_rootindex/view.qml 0
-
- If the \l model is a QAbstractItemModel subclass, the delegate can also
- reference a \c hasModelChildren property (optionally qualified by a
- \e model. prefix) that indicates whether the delegate's model item has
- any child nodes.
-
-
- \sa modelIndex(), parentModelIndex()
-*/
-QVariant QQuickVisualDataModel::rootIndex() const
-{
- Q_D(const QQuickVisualDataModel);
- return QVariant::fromValue(QModelIndex(d->m_adaptorModel.rootIndex));
-}
-
-void QQuickVisualDataModel::setRootIndex(const QVariant &root)
-{
- Q_D(QQuickVisualDataModel);
-
- QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
- const bool changed = d->m_adaptorModel.rootIndex != modelIndex;
- if (changed || !d->m_adaptorModel.isValid()) {
- const int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = modelIndex;
- if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) // The previous root index was invalidated, so we need to reconnect the model.
- d->m_adaptorModel.setModel(d->m_adaptorModel.list.list(), this, d->m_context->engine());
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
- if (d->m_complete) {
- const int newCount = d->m_adaptorModel.count();
- if (oldCount)
- _q_itemsRemoved(0, oldCount);
- if (newCount)
- _q_itemsInserted(0, newCount);
- }
- if (changed)
- emit rootIndexChanged();
- }
-}
-
-/*!
- \qmlmethod QModelIndex QtQuick2::VisualDataModel::modelIndex(int index)
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the specified index.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQuickVisualDataModel::modelIndex(int idx) const
-{
- Q_D(const QQuickVisualDataModel);
- return d->m_adaptorModel.modelIndex(idx);
-}
-
-/*!
- \qmlmethod QModelIndex QtQuick2::VisualDataModel::parentModelIndex()
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the parent of the current rootIndex.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQuickVisualDataModel::parentModelIndex() const
-{
- Q_D(const QQuickVisualDataModel);
- return d->m_adaptorModel.parentModelIndex();
-}
-
-/*!
- \qmlproperty int QtQuick2::VisualDataModel::count
-*/
-
-int QQuickVisualDataModel::count() const
-{
- Q_D(const QQuickVisualDataModel);
- if (!d->m_delegate)
- return 0;
- return d->m_compositor.count(d->m_compositorGroup);
-}
-
-QQuickVisualDataModel::ReleaseFlags QQuickVisualDataModelPrivate::release(QObject *object)
-{
- QQuickVisualDataModel::ReleaseFlags stat = 0;
- if (!object)
- return stat;
-
- if (QQuickVisualDataModelItem *cacheItem = QQuickVisualDataModelItem::dataForObject(object)) {
- if (cacheItem->releaseObject()) {
- cacheItem->destroyObject();
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
- emitDestroyingItem(item);
- if (cacheItem->incubationTask) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = 0;
- }
- cacheItem->Dispose();
- stat |= QQuickVisualModel::Destroyed;
- } else {
- stat |= QQuickVisualDataModel::Referenced;
- }
- }
- return stat;
-}
-
-/*
- Returns ReleaseStatus flags.
-*/
-
-QQuickVisualDataModel::ReleaseFlags QQuickVisualDataModel::release(QQuickItem *item)
-{
- Q_D(QQuickVisualDataModel);
- QQuickVisualModel::ReleaseFlags stat = d->release(item);
- if (stat & Destroyed)
- item->setParentItem(0);
- return stat;
-}
-
-// Cancel a requested async item
-void QQuickVisualDataModel::cancel(int index)
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "VisualDataModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return;
- }
-
- Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
- QQuickVisualDataModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex) : 0;
- if (cacheItem) {
- if (cacheItem->incubationTask && !cacheItem->isObjectReferenced()) {
- d->releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = 0;
-
- if (cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
- d->emitDestroyingItem(item);
- else if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- d->emitDestroyingPackage(package);
- }
-
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- d->m_compositor.clearFlags(Compositor::Cache, it.cacheIndex, 1, Compositor::CacheFlag);
- d->m_cache.removeAt(it.cacheIndex);
- delete cacheItem;
- Q_ASSERT(d->m_cache.count() == d->m_compositor.count(Compositor::Cache));
- }
- }
-}
-
-void QQuickVisualDataModelPrivate::group_append(
- QQmlListProperty<QQuickVisualDataGroup> *property, QQuickVisualDataGroup *group)
-{
- QQuickVisualDataModelPrivate *d = static_cast<QQuickVisualDataModelPrivate *>(property->data);
- if (d->m_complete)
- return;
- if (d->m_groupCount == Compositor::MaximumGroupCount) {
- qmlInfo(d->q_func()) << QQuickVisualDataModel::tr("The maximum number of supported VisualDataGroups is 8");
- return;
- }
- d->m_groups[d->m_groupCount] = group;
- d->m_groupCount += 1;
-}
-
-int QQuickVisualDataModelPrivate::group_count(
- QQmlListProperty<QQuickVisualDataGroup> *property)
-{
- QQuickVisualDataModelPrivate *d = static_cast<QQuickVisualDataModelPrivate *>(property->data);
- return d->m_groupCount - 1;
-}
-
-QQuickVisualDataGroup *QQuickVisualDataModelPrivate::group_at(
- QQmlListProperty<QQuickVisualDataGroup> *property, int index)
-{
- QQuickVisualDataModelPrivate *d = static_cast<QQuickVisualDataModelPrivate *>(property->data);
- return index >= 0 && index < d->m_groupCount - 1
- ? d->m_groups[index + 1]
- : 0;
-}
-
-/*!
- \qmlproperty list<VisualDataGroup> QtQuick2::VisualDataModel::groups
-
- This property holds a visual data model's group definitions.
-
- Groups define a sub-set of the items in a visual data model and can be used to filter
- a model.
-
- For every group defined in a VisualDataModel two attached properties are added to each
- delegate item. The first of the form VisualDataModel.in\e{GroupName} holds whether the
- item belongs to the group and the second VisualDataModel.\e{groupName}Index holds the
- index of the item in that group.
-
- The following example illustrates using groups to select items in a model.
-
- \snippet qml/visualdatagroup.qml 0
-*/
-
-QQmlListProperty<QQuickVisualDataGroup> QQuickVisualDataModel::groups()
-{
- Q_D(QQuickVisualDataModel);
- return QQmlListProperty<QQuickVisualDataGroup>(
- this,
- d,
- QQuickVisualDataModelPrivate::group_append,
- QQuickVisualDataModelPrivate::group_count,
- QQuickVisualDataModelPrivate::group_at,
- 0);
-}
-
-/*!
- \qmlproperty VisualDataGroup QtQuick2::VisualDataModel::items
-
- This property holds visual data model's default group to which all new items are added.
-*/
-
-QQuickVisualDataGroup *QQuickVisualDataModel::items()
-{
- Q_D(QQuickVisualDataModel);
- return d->m_items;
-}
-
-/*!
- \qmlproperty VisualDataGroup QtQuick2::VisualDataModel::persistedItems
-
- This property holds visual data model's persisted items group.
-
- Items in this group are not destroyed when released by a view, instead they are persisted
- until removed from the group.
-
- An item can be removed from the persistedItems group by setting the
- VisualDataModel.inPersistedItems property to false. If the item is not referenced by a view
- at that time it will be destroyed. Adding an item to this group will not create a new
- instance.
-
- Items returned by the \l QtQuick2::VisualDataGroup::create() function are automatically added
- to this group.
-*/
-
-QQuickVisualDataGroup *QQuickVisualDataModel::persistedItems()
-{
- Q_D(QQuickVisualDataModel);
- return d->m_persistedItems;
-}
-
-/*!
- \qmlproperty string QtQuick2::VisualDataModel::filterOnGroup
-
- This property holds the name of the group used to filter the visual data model.
-
- Only items which belong to this group are visible to a view.
-
- By default this is the \l items group.
-*/
-
-QString QQuickVisualDataModel::filterGroup() const
-{
- Q_D(const QQuickVisualDataModel);
- return d->m_filterGroup;
-}
-
-void QQuickVisualDataModel::setFilterGroup(const QString &group)
-{
- Q_D(QQuickVisualDataModel);
-
- if (d->m_transaction) {
- qmlInfo(this) << tr("The group of a VisualDataModel cannot be changed within onChanged");
- return;
- }
-
- if (d->m_filterGroup != group) {
- d->m_filterGroup = group;
- d->updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQuickVisualDataModel::resetFilterGroup()
-{
- setFilterGroup(QStringLiteral("items"));
-}
-
-void QQuickVisualDataModelPrivate::updateFilterGroup()
-{
- Q_Q(QQuickVisualDataModel);
- if (!m_cacheMetaType)
- return;
-
- QQuickListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- for (int i = 1; i < m_groupCount; ++i) {
- if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQuickVisualDataGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQuickChangeSet::Remove> removes;
- QVector<QQuickChangeSet::Insert> inserts;
- m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQuickChangeSet changeSet;
- changeSet.move(removes, inserts);
- emit q->modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit q->countChanged();
-
- if (m_parts) {
- foreach (QQuickVisualPartsModel *model, m_parts->models)
- model->updateFilterGroup(m_compositorGroup, changeSet);
- }
- }
-}
-
-/*!
- \qmlproperty object QtQuick2::VisualDataModel::parts
-
- The \a parts property selects a VisualDataModel which creates
- delegates from the part named. This is used in conjunction with
- the \l Package type.
-
- For example, the code below selects a model which creates
- delegates named \e list from a \l Package:
-
- \code
- VisualDataModel {
- id: visualModel
- delegate: Package {
- Item { Package.name: "list" }
- }
- model: myModel
- }
-
- ListView {
- width: 200; height:200
- model: visualModel.parts.list
- }
- \endcode
-
- \sa Package
-*/
-
-QObject *QQuickVisualDataModel::parts()
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_parts)
- d->m_parts = new QQuickVisualDataModelParts(this);
- return d->m_parts;
-}
-
-void QQuickVisualDataModelPrivate::emitCreatedPackage(QVDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
-}
-
-void QQuickVisualDataModelPrivate::emitInitPackage(QVDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
-}
-
-void QQuickVisualDataModelPrivate::emitDestroyingPackage(QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->destroyingPackage(package);
-}
-
-void QVDMIncubationTask::statusChanged(Status status)
-{
- vdm->incubatorStatusChanged(this, status);
-}
-
-void QQuickVisualDataModelPrivate::releaseIncubator(QVDMIncubationTask *incubationTask)
-{
- Q_Q(QQuickVisualDataModel);
- if (!incubationTask->isError())
- incubationTask->clear();
- m_finishedIncubating.append(incubationTask);
- if (!m_incubatorCleanupScheduled) {
- m_incubatorCleanupScheduled = true;
- QCoreApplication::postEvent(q, new QEvent(QEvent::User));
- }
-}
-
-void QQuickVisualDataModelPrivate::removeCacheItem(QQuickVisualDataModelItem *cacheItem)
-{
- int cidx = m_cache.indexOf(cacheItem);
- if (cidx >= 0) {
- m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
- m_cache.removeAt(cidx);
- }
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
-}
-
-void QQuickVisualDataModelPrivate::incubatorStatusChanged(QVDMIncubationTask *incubationTask, QQmlIncubator::Status status)
-{
- Q_Q(QQuickVisualDataModel);
- if (status != QQmlIncubator::Ready && status != QQmlIncubator::Error)
- return;
-
- QQuickVisualDataModelItem *cacheItem = incubationTask->incubating;
- cacheItem->incubationTask = 0;
- incubationTask->incubating = 0;
- releaseIncubator(incubationTask);
-
- if (status == QQmlIncubator::Ready) {
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(cacheItem->object))
- emitCreatedItem(incubationTask, item);
- else if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitCreatedPackage(incubationTask, package);
- } else if (status == QQmlIncubator::Error) {
- qmlInfo(q, m_delegate->errors()) << "Error creating delegate";
- }
-
- if (!cacheItem->isObjectReferenced()) {
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(cacheItem->object))
- emitDestroyingItem(item);
- else if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitDestroyingPackage(package);
- delete cacheItem->object;
- cacheItem->object = 0;
- cacheItem->scriptRef -= 1;
- cacheItem->contextData->destroy();
- cacheItem->contextData = 0;
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
- }
-}
-
-void QVDMIncubationTask::setInitialState(QObject *o)
-{
- vdm->setInitialState(this, o);
-}
-
-void QQuickVisualDataModelPrivate::setInitialState(QVDMIncubationTask *incubationTask, QObject *o)
-{
- QQuickVisualDataModelItem *cacheItem = incubationTask->incubating;
- cacheItem->object = o;
-
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(cacheItem->object))
- emitInitItem(incubationTask, item);
- else if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitInitPackage(incubationTask, package);
-}
-
-QObject *QQuickVisualDataModelPrivate::object(Compositor::Group group, int index, bool asynchronous)
-{
- Q_Q(QQuickVisualDataModel);
- if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
- qWarning() << "VisualDataModel::item: index out range" << index << m_compositor.count(group);
- return 0;
- } else if (!m_context->isValid()) {
- return 0;
- }
-
- Compositor::iterator it = m_compositor.find(group, index);
-
- QQuickVisualDataModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0;
-
- if (!cacheItem) {
- cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), it.modelIndex());
- if (!cacheItem)
- return 0;
-
- cacheItem->groups = it->flags;
-
- m_cache.insert(it.cacheIndex, cacheItem);
- m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- }
-
- // Bump the reference counts temporarily so neither the content data or the delegate object
- // are deleted if incubatorStatusChanged() is called synchronously.
- cacheItem->scriptRef += 1;
- cacheItem->referenceObject();
-
- if (cacheItem->incubationTask) {
- if (!asynchronous && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
- // previously requested async - now needed immediately
- cacheItem->incubationTask->forceCompletion();
- }
- } else if (!cacheItem->object) {
- QQmlContext *creationContext = m_delegate->creationContext();
-
- cacheItem->scriptRef += 1;
-
- cacheItem->incubationTask = new QVDMIncubationTask(this, asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
- cacheItem->incubationTask->incubating = cacheItem;
- cacheItem->incubationTask->clear();
-
- for (int i = 1; i < m_groupCount; ++i)
- cacheItem->incubationTask->index[i] = it.index[i];
-
- QQmlContextData *ctxt = new QQmlContextData;
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context));
- ctxt->contextObject = cacheItem;
- cacheItem->contextData = ctxt;
-
- if (m_adaptorModel.hasProxyObject()) {
- if (QQuickVisualAdaptorModelProxyInterface *proxy
- = qobject_cast<QQuickVisualAdaptorModelProxyInterface *>(cacheItem)) {
- ctxt = new QQmlContextData;
- ctxt->setParent(cacheItem->contextData, true);
- ctxt->contextObject = proxy->proxiedObject();
- }
- }
-
- cacheItem->incubateObject(
- m_delegate,
- m_context->engine(),
- ctxt,
- QQmlContextData::get(m_context));
- }
-
- if (index == m_compositor.count(group) - 1 && m_adaptorModel.canFetchMore())
- QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
-
- // Remove the temporary reference count.
- cacheItem->scriptRef -= 1;
- if (cacheItem->object)
- return cacheItem->object;
-
- cacheItem->releaseObject();
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
-
- return 0;
-}
-
-/*
- If asynchronous is true or the component is being loaded asynchronously due
- to an ancestor being loaded asynchronously, item() may return 0. In this
- case itemCreated() will be emitted when the item is available. The item
- at this stage does not have any references, so item() must be called again
- to ensure a reference is held. Any call to item() which returns a valid item
- must be matched by a call to release() in order to destroy the item.
-*/
-QQuickItem *QQuickVisualDataModel::item(int index, bool asynchronous)
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "VisualDataModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return 0;
- }
-
- QObject *object = d->object(d->m_compositorGroup, index, asynchronous);
- if (!object)
- return 0;
-
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
- return item;
-
- d->release(object);
- if (!d->m_delegateValidated) {
- if (object)
- qmlInfo(d->m_delegate) << QQuickVisualDataModel::tr("Delegate component must be Item type.");
- d->m_delegateValidated = true;
- }
- return 0;
-}
-
-QString QQuickVisualDataModelPrivate::stringValue(Compositor::Group group, int index, const QString &name)
-{
- Compositor::iterator it = m_compositor.find(group, index);
- if (QQuickVisualAdaptorModel *model = it.list<QQuickVisualAdaptorModel>()) {
- QString role = name;
- int dot = name.indexOf(QLatin1Char('.'));
- if (dot > 0)
- role = name.left(dot);
- QVariant value = model->value(it.modelIndex(), role);
- while (dot > 0) {
- QObject *obj = qvariant_cast<QObject*>(value);
- if (!obj)
- return QString();
- int from = dot+1;
- dot = name.indexOf(QLatin1Char('.'), from);
- value = obj->property(name.mid(from, dot-from).toUtf8());
- }
- return value.toString();
- }
- return QString();
-}
-
-QString QQuickVisualDataModel::stringValue(int index, const QString &name)
-{
- Q_D(QQuickVisualDataModel);
- return d->stringValue(d->m_compositorGroup, index, name);
-}
-
-int QQuickVisualDataModel::indexOf(QQuickItem *item, QObject *) const
-{
- Q_D(const QQuickVisualDataModel);
- if (QQuickVisualDataModelItem *cacheItem = QQuickVisualDataModelItem::dataForObject(item))
- return cacheItem->groupIndex(d->m_compositorGroup);
- return -1;
-}
-
-void QQuickVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
-{
- Q_D(QQuickVisualDataModel);
- d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
- d->m_watchedRoles = roles;
-}
-
-void QQuickVisualDataModelPrivate::addGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Insert> inserts;
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- emitChanges();
-}
-
-void QQuickVisualDataModelPrivate::removeGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- m_compositor.clearFlags(from, count, group, groupFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-void QQuickVisualDataModelPrivate::setGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- const int removeFlags = ~groupFlags & Compositor::GroupMask;
-
- from = m_compositor.find(from.group, from.index[from.group]);
- m_compositor.clearFlags(from, count, group, removeFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-bool QQuickVisualDataModel::event(QEvent *e)
-{
- Q_D(QQuickVisualDataModel);
- if (e->type() == QEvent::UpdateRequest) {
- d->m_adaptorModel.fetchMore();
- } else if (e->type() == QEvent::User) {
- d->m_incubatorCleanupScheduled = false;
- qDeleteAll(d->m_finishedIncubating);
- d->m_finishedIncubating.clear();
- }
- return QQuickVisualModel::event(e);
-}
-
-void QQuickVisualDataModelPrivate::itemsChanged(const QVector<Compositor::Change> &changes)
-{
- if (!m_delegate)
- return;
-
- QVarLengthArray<QVector<QQuickChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
-
- foreach (const Compositor::Change &change, changes) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (change.inGroup(i)) {
- translatedChanges[i].append(QQuickChangeSet::Change(change.index[i], change.count));
- }
- }
- }
-
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
-}
-
-void QQuickVisualDataModel::_q_itemsChanged(int index, int count, const QVector<int> &roles)
-{
- Q_D(QQuickVisualDataModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
- QVector<Compositor::Change> changes;
- d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
- d->itemsChanged(changes);
- d->emitChanges();
- }
-}
-
-static void incrementIndexes(QQuickVisualDataModelItem *cacheItem, int count, const int *deltas)
-{
- if (QVDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < count; ++i)
- incubationTask->index[i] += deltas[i];
- }
- if (QQuickVisualDataModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < count; ++i)
- attached->m_currentIndex[i] += deltas[i];
- }
-}
-
-void QQuickVisualDataModelPrivate::itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQuickChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQuickVisualDataModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
-
- int inserted[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- inserted[i] = 0;
-
- foreach (const Compositor::Insert &insert, inserts) {
- for (; cacheIndex < insert.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (insert.inGroup(i)) {
- (*translatedInserts)[i].append(
- QQuickChangeSet::Insert(insert.index[i], insert.count, insert.moveId));
- inserted[i] += insert.count;
- }
- }
-
- if (!insert.inCache())
- continue;
-
- if (movedItems && insert.isMove()) {
- QList<QQuickVisualDataModelItem *> items = movedItems->take(insert.moveId);
- Q_ASSERT(items.count() == insert.count);
- m_cache = m_cache.mid(0, insert.cacheIndex) + items + m_cache.mid(insert.cacheIndex);
- }
- if (insert.inGroup()) {
- for (int offset = 0; cacheIndex < insert.cacheIndex + insert.count; ++cacheIndex, ++offset) {
- QQuickVisualDataModelItem *cacheItem = m_cache.at(cacheIndex);
- cacheItem->groups |= insert.flags & Compositor::GroupMask;
-
- if (QVDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- if (QQuickVisualDataModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- }
- } else {
- cacheIndex = insert.cacheIndex + insert.count;
- }
- }
- for (; cacheIndex < m_cache.count(); ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
-}
-
-void QQuickVisualDataModelPrivate::itemsInserted(const QVector<Compositor::Insert> &inserts)
-{
- QVarLengthArray<QVector<QQuickChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
-}
-
-void QQuickVisualDataModel::_q_itemsInserted(int index, int count)
-{
-
- Q_D(QQuickVisualDataModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- d->m_count += count;
-
- for (int i = 0, c = d->m_cache.count(); i < c; ++i) {
- QQuickVisualDataModelItem *item = d->m_cache.at(i);
- if (item->modelIndex() >= index)
- item->setModelIndex(item->modelIndex() + count);
- }
-
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
- d->itemsInserted(inserts);
- d->emitChanges();
-}
-
-void QQuickVisualDataModelPrivate::itemsRemoved(
- const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQuickChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
- QHash<int, QList<QQuickVisualDataModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
- int removedCache = 0;
-
- int removed[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- removed[i] = 0;
-
- foreach (const Compositor::Remove &remove, removes) {
- for (; cacheIndex < remove.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i)) {
- (*translatedRemoves)[i].append(
- QQuickChangeSet::Remove(remove.index[i], remove.count, remove.moveId));
- removed[i] -= remove.count;
- }
- }
-
- if (!remove.inCache())
- continue;
-
- if (movedItems && remove.isMove()) {
- movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex, remove.count));
- QList<QQuickVisualDataModelItem *>::iterator begin = m_cache.begin() + remove.cacheIndex;
- QList<QQuickVisualDataModelItem *>::iterator end = begin + remove.count;
- m_cache.erase(begin, end);
- } else {
- for (; cacheIndex < remove.cacheIndex + remove.count - removedCache; ++cacheIndex) {
- QQuickVisualDataModelItem *cacheItem = m_cache.at(cacheIndex);
- if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emitDestroyingPackage(package);
- else if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
- emitDestroyingItem(item);
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
- m_cache.removeAt(cacheIndex);
- delete cacheItem;
- --cacheIndex;
- ++removedCache;
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- } else if (remove.groups() == cacheItem->groups) {
- cacheItem->groups = 0;
- if (QVDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = -1;
- }
- if (QQuickVisualDataModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = -1;
- }
- } else {
- if (QVDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- incubationTask->index[i] = remove.index[i];
- }
- }
- if (QQuickVisualDataModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- attached->m_currentIndex[i] = remove.index[i];
- }
- }
- cacheItem->groups &= ~remove.flags;
- }
- }
- }
- }
-
- for (; cacheIndex < m_cache.count(); ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
-}
-
-void QQuickVisualDataModelPrivate::itemsRemoved(const QVector<Compositor::Remove> &removes)
-{
- QVarLengthArray<QVector<QQuickChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
-}
-
-void QQuickVisualDataModel::_q_itemsRemoved(int index, int count)
-{
- Q_D(QQuickVisualDataModel);
- if (count <= 0|| !d->m_complete)
- return;
-
- d->m_count -= count;
-
- for (int i = 0, c = d->m_cache.count(); i < c; ++i) {
- QQuickVisualDataModelItem *item = d->m_cache.at(i);
- if (item->modelIndex() >= index + count)
- item->setModelIndex(item->modelIndex() - count);
- else if (item->modelIndex() >= index)
- item->setModelIndex(-1);
- }
-
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
- d->itemsRemoved(removes);
-
- d->emitChanges();
-}
-
-void QQuickVisualDataModelPrivate::itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts)
-{
- QHash<int, QList<QQuickVisualDataModelItem *> > movedItems;
-
- QVarLengthArray<QVector<QQuickChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves, &movedItems);
-
- QVarLengthArray<QVector<QQuickChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts, &movedItems);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- Q_ASSERT(movedItems.isEmpty());
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i) {
- QQuickVisualDataGroupPrivate::get(m_groups[i])->changeSet.move(
- translatedRemoves.at(i),
- translatedInserts.at(i));
- }
-}
-
-void QQuickVisualDataModel::_q_itemsMoved(int from, int to, int count)
-{
- Q_D(QQuickVisualDataModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- const int minimum = qMin(from, to);
- const int maximum = qMax(from, to) + count;
- const int difference = from > to ? count : -count;
-
- for (int i = 0, c = d->m_cache.count(); i < c; ++i) {
- QQuickVisualDataModelItem *item = d->m_cache.at(i);
- if (item->modelIndex() >= from && item->modelIndex() < from + count)
- item->setModelIndex(item->modelIndex() - from + to);
- else if (item->modelIndex() >= minimum && item->modelIndex() < maximum)
- item->setModelIndex(item->modelIndex() + difference);
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
- d->itemsMoved(removes, inserts);
- d->emitChanges();
-}
-
-template <typename T> v8::Local<v8::Array>
-QQuickVisualDataModelPrivate::buildChangeList(const QVector<T> &changes)
-{
- v8::Local<v8::Array> indexes = v8::Array::New(changes.count());
- v8::Local<v8::String> indexKey = v8::String::New("index");
- v8::Local<v8::String> countKey = v8::String::New("count");
- v8::Local<v8::String> moveIdKey = v8::String::New("moveId");
-
- for (int i = 0; i < changes.count(); ++i) {
- v8::Local<v8::Object> object = v8::Object::New();
- object->Set(indexKey, v8::Integer::New(changes.at(i).index));
- object->Set(countKey, v8::Integer::New(changes.at(i).count));
- object->Set(moveIdKey, changes.at(i).moveId != -1 ? v8::Integer::New(changes.at(i).count) : v8::Undefined());
- indexes->Set(i, object);
- }
- return indexes;
-}
-
-void QQuickVisualDataModelPrivate::emitModelUpdated(const QQuickChangeSet &changeSet, bool reset)
-{
- Q_Q(QQuickVisualDataModel);
- emit q->modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQuickVisualDataModelPrivate::emitChanges()
-{
- if (m_transaction || !m_complete || !m_context->isValid())
- return;
-
- m_transaction = true;
- QV8Engine *engine = QQmlEnginePrivate::getV8Engine(m_context->engine());
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->emitChanges(engine);
- m_transaction = false;
-
- const bool reset = m_reset;
- m_reset = false;
- for (int i = 1; i < m_groupCount; ++i)
- QQuickVisualDataGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
-
- foreach (QQuickVisualDataModelItem *cacheItem, m_cache) {
- if (cacheItem->attached)
- cacheItem->attached->emitChanges();
- }
-}
-
-void QQuickVisualDataModel::_q_modelReset()
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_delegate)
- return;
-
- int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = QModelIndex();
-
- if (d->m_complete) {
- d->m_count = d->m_adaptorModel.count();
-
- for (int i = 0, c = d->m_cache.count(); i < c; ++i) {
- QQuickVisualDataModelItem *item = d->m_cache.at(i);
- if (item->modelIndex() != -1)
- item->setModelIndex(-1);
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- if (oldCount)
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- if (d->m_count)
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
- d->itemsMoved(removes, inserts);
- d->m_reset = true;
-
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
-
- d->emitChanges();
- }
- emit rootIndexChanged();
-}
-
-void QQuickVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQuickVisualDataModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsInserted(begin, end - begin + 1);
-}
-
-void QQuickVisualDataModel::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQuickVisualDataModel);
- if (!d->m_adaptorModel.rootIndex.isValid())
- return;
- const QModelIndex index = d->m_adaptorModel.rootIndex;
- if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
- const int oldCount = d->m_count;
- d->m_count = 0;
- d->m_adaptorModel.invalidateModel(this);
-
- if (d->m_complete && oldCount > 0) {
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- d->itemsRemoved(removes);
- d->emitChanges();
- }
- }
-}
-
-void QQuickVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQuickVisualDataModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsRemoved(begin, end - begin + 1);
-}
-
-void QQuickVisualDataModel::_q_rowsMoved(
- const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
- const QModelIndex &destinationParent, int destinationRow)
-{
- Q_D(QQuickVisualDataModel);
- const int count = sourceEnd - sourceStart + 1;
- if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
- } else if (sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsRemoved(sourceStart, count);
- } else if (destinationParent == d->m_adaptorModel.rootIndex) {
- _q_itemsInserted(destinationRow, count);
- }
-}
-
-void QQuickVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
-{
- Q_D(QQuickVisualDataModel);
- if (begin.parent() == d->m_adaptorModel.rootIndex)
- _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
-}
-
-void QQuickVisualDataModel::_q_layoutChanged()
-{
- Q_D(QQuickVisualDataModel);
- _q_itemsChanged(0, d->m_count, QVector<int>());
-}
-
-QQuickVisualDataModelAttached *QQuickVisualDataModel::qmlAttachedProperties(QObject *obj)
-{
- if (QQuickVisualDataModelItem *cacheItem = QQuickVisualDataModelItem::dataForObject(obj)) {
- if (cacheItem->object == obj) { // Don't create attached item for child objects.
- cacheItem->attached = new QQuickVisualDataModelAttached(cacheItem, obj);
- return cacheItem->attached;
- }
- }
- return new QQuickVisualDataModelAttached(obj);
-}
-
-bool QQuickVisualDataModelPrivate::insert(
- Compositor::insert_iterator &before, const v8::Local<v8::Object> &object, int groups)
-{
- if (!m_context->isValid())
- return false;
-
- QQuickVisualDataModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1);
- if (!cacheItem)
- return false;
-
- v8::Local<v8::Array> propertyNames = object->GetPropertyNames();
- for (uint i = 0; i < propertyNames->Length(); ++i) {
- v8::Local<v8::String> propertyName = propertyNames->Get(i)->ToString();
- cacheItem->setValue(
- m_cacheMetaType->v8Engine->toString(propertyName),
- m_cacheMetaType->v8Engine->toVariant(object->Get(propertyName), QVariant::Invalid));
- }
-
- cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
-
- // Must be before the new object is inserted into the cache or its indexes will be adjusted too.
- itemsInserted(QVector<Compositor::Insert>() << Compositor::Insert(before, 1, cacheItem->groups & ~Compositor::CacheFlag));
-
- before = m_compositor.insert(before, 0, 0, 1, cacheItem->groups);
- m_cache.insert(before.cacheIndex, cacheItem);
-
- return true;
-}
-
-//============================================================================
-
-QQuickVisualDataModelItemMetaType::QQuickVisualDataModelItemMetaType(
- QV8Engine *engine, QQuickVisualDataModel *model, const QStringList &groupNames)
- : model(model)
- , groupCount(groupNames.count() + 1)
- , v8Engine(engine)
- , metaObject(0)
- , groupNames(groupNames)
-{
-}
-
-QQuickVisualDataModelItemMetaType::~QQuickVisualDataModelItemMetaType()
-{
- if (metaObject)
- metaObject->release();
- qPersistentDispose(constructor);
-}
-
-void QQuickVisualDataModelItemMetaType::initializeMetaObject()
-{
- QMetaObjectBuilder builder;
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- builder.setClassName(QQuickVisualDataModelAttached::staticMetaObject.className());
- builder.setSuperClass(&QQuickVisualDataModelAttached::staticMetaObject);
-
- int notifierId = 0;
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- QString propertyName = QStringLiteral("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "bool", notifierId);
- propertyBuilder.setWritable(true);
- }
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "int", notifierId);
- propertyBuilder.setWritable(true);
- }
-
- metaObject = new QQuickVisualDataModelAttachedMetaObject(this, builder.toMetaObject());
-}
-
-void QQuickVisualDataModelItemMetaType::initializeConstructor()
-{
- v8::HandleScope handleScope;
- v8::Context::Scope contextScope(v8Engine->context());
-
- QQuickVisualDataModelEngineData *data = engineData(v8Engine);
-
- constructor = qPersistentNew(v8::ObjectTemplate::New());
-
- constructor->SetHasExternalResource(true);
- constructor->SetAccessor(data->model(), get_model);
- constructor->SetAccessor(data->groups(), get_groups, set_groups);
- constructor->SetAccessor(data->isUnresolved(), get_member, 0, v8::Int32::New(30));
- constructor->SetAccessor(data->inItems(), get_member, set_member, v8::Int32::New(1));
- constructor->SetAccessor(data->inPersistedItems(), get_member, set_member, v8::Int32::New(2));
- constructor->SetAccessor(data->itemsIndex(), get_index, 0, v8::Int32::New(1));
- constructor->SetAccessor(data->persistedItemsIndex(), get_index, 0, v8::Int32::New(2));
-
- for (int i = 2; i < groupNames.count(); ++i) {
- QString propertyName = QStringLiteral("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- constructor->SetAccessor(
- v8Engine->toString(propertyName), get_member, set_member, v8::Int32::New(i + 1));
- }
- for (int i = 2; i < groupNames.count(); ++i) {
- const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
- constructor->SetAccessor(
- v8Engine->toString(propertyName), get_index, 0, v8::Int32::New(i + 1));
- }
-}
-
-int QQuickVisualDataModelItemMetaType::parseGroups(const QStringList &groups) const
-{
- int groupFlags = 0;
- foreach (const QString &groupName, groups) {
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- return groupFlags;
-}
-
-int QQuickVisualDataModelItemMetaType::parseGroups(const v8::Local<v8::Value> &groups) const
-{
- int groupFlags = 0;
- if (groups->IsString()) {
- const QString groupName = v8Engine->toString(groups);
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- } else if (groups->IsArray()) {
- v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(groups);
- for (uint i = 0; i < array->Length(); ++i) {
- const QString groupName = v8Engine->toString(array->Get(i));
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- }
- return groupFlags;
-}
-
-v8::Handle<v8::Value> QQuickVisualDataModelItemMetaType::get_model(
- v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(cacheItem, "Not a valid VisualData object");
- if (!cacheItem->metaType->model)
- return v8::Undefined();
-
- return cacheItem->get();
-}
-
-v8::Handle<v8::Value> QQuickVisualDataModelItemMetaType::get_groups(
- v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(cacheItem, "Not a valid VisualData object");
-
- QStringList groups;
- for (int i = 1; i < cacheItem->metaType->groupCount; ++i) {
- if (cacheItem->groups & (1 << i))
- groups.append(cacheItem->metaType->groupNames.at(i - 1));
- }
-
- return cacheItem->engine->fromVariant(groups);
-}
-
-void QQuickVisualDataModelItemMetaType::set_groups(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE_SETTER(cacheItem, "Not a valid VisualData object");
-
- if (!cacheItem->metaType->model)
- return;
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(cacheItem->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(value);
- const int cacheIndex = model->m_cache.indexOf(cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
-}
-
-v8::Handle<v8::Value> QQuickVisualDataModelItemMetaType::get_member(
- v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(cacheItem, "Not a valid VisualData object");
-
- return v8::Boolean::New(cacheItem->groups & (1 << info.Data()->Int32Value()));
-}
-
-void QQuickVisualDataModelItemMetaType::set_member(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE_SETTER(cacheItem, "Not a valid VisualData object");
-
- if (!cacheItem->metaType->model)
- return;
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(cacheItem->metaType->model);
-
- Compositor::Group group = Compositor::Group(info.Data()->Int32Value());
- const bool member = value->BooleanValue();
- const int groupFlag = (1 << group);
- if (member == ((cacheItem->groups & groupFlag) != 0))
- return;
-
- const int cacheIndex = model->m_cache.indexOf(cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- if (member)
- model->addGroups(it, 1, Compositor::Cache, groupFlag);
- else
- model->removeGroups(it, 1, Compositor::Cache, groupFlag);
-}
-
-v8::Handle<v8::Value> QQuickVisualDataModelItemMetaType::get_index(
- v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QQuickVisualDataModelItem *cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
- V8ASSERT_TYPE(cacheItem, "Not a valid VisualData object");
-
- return v8::Integer::New(cacheItem->groupIndex(Compositor::Group(info.Data()->Int32Value())));
-}
-
-
-//---------------------------------------------------------------------------
-
-QQuickVisualDataModelItem::QQuickVisualDataModelItem(
- QQuickVisualDataModelItemMetaType *metaType, int modelIndex)
- : QV8ObjectResource(metaType->v8Engine)
- , metaType(metaType)
- , contextData(0)
- , object(0)
- , attached(0)
- , incubationTask(0)
- , objectRef(0)
- , scriptRef(0)
- , groups(0)
- , index(modelIndex)
-{
- metaType->addref();
-}
-
-QQuickVisualDataModelItem::~QQuickVisualDataModelItem()
-{
- Q_ASSERT(scriptRef == 0);
- Q_ASSERT(objectRef == 0);
- Q_ASSERT(!object);
-
- if (incubationTask && metaType->model)
- QQuickVisualDataModelPrivate::get(metaType->model)->releaseIncubator(incubationTask);
-
- metaType->release();
-
-}
-
-void QQuickVisualDataModelItem::Dispose()
-{
- --scriptRef;
- if (isReferenced())
- return;
-
- if (metaType->model) {
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(metaType->model);
- model->removeCacheItem(this);
- }
- delete this;
-}
-
-/*
- This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData
- arguments instead of QQmlContext which means we don't have to construct the rather weighty
- wrapper class for every delegate item.
-*/
-void QQuickVisualDataModelItem::incubateObject(
- QQmlComponent *component,
- QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext)
-{
- QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask);
- QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
- QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component);
-
- incubatorPriv->compiledData = componentPriv->cc;
- incubatorPriv->compiledData->addref();
- incubatorPriv->vme.init(
- context,
- componentPriv->cc,
- componentPriv->start,
- componentPriv->creationContext);
-
- enginePriv->incubate(*incubationTask, forContext);
-}
-
-void QQuickVisualDataModelItem::destroyObject()
-{
- Q_ASSERT(object);
- Q_ASSERT(contextData);
-
- QObjectPrivate *p = QObjectPrivate::get(object);
- Q_ASSERT(p->declarativeData);
- QQmlData *data = static_cast<QQmlData*>(p->declarativeData);
- if (data->ownContext && data->context)
- data->context->clearContext();
- object->deleteLater();
-
- if (attached) {
- attached->m_cacheItem = 0;
- attached = 0;
- }
-
- contextData->destroy();
- contextData = 0;
- object = 0;
-}
-
-QQuickVisualDataModelItem *QQuickVisualDataModelItem::dataForObject(QObject *object)
-{
- QObjectPrivate *p = QObjectPrivate::get(object);
- QQmlContextData *context = p->declarativeData
- ? static_cast<QQmlData *>(p->declarativeData)->context
- : 0;
- for (context = context ? context->parent : 0; context; context = context->parent) {
- if (QQuickVisualDataModelItem *cacheItem = qobject_cast<QQuickVisualDataModelItem *>(
- context->contextObject)) {
- return cacheItem;
- }
- }
- return 0;
-}
-
-int QQuickVisualDataModelItem::groupIndex(Compositor::Group group)
-{
- if (QQuickVisualDataModelPrivate * const model = metaType->model
- ? QQuickVisualDataModelPrivate::get(metaType->model)
- : 0) {
- return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(this)).index[group];
- }
- return -1;
-}
-
-//---------------------------------------------------------------------------
-
-QQuickVisualDataModelAttachedMetaObject::QQuickVisualDataModelAttachedMetaObject(
- QQuickVisualDataModelItemMetaType *metaType, QMetaObject *metaObject)
- : metaType(metaType)
- , metaObject(metaObject)
- , memberPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount())
- , indexPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount() + metaType->groupNames.count())
-{
- // Don't reference count the meta-type here as that would create a circular reference.
- // Instead we rely the fact that the meta-type's reference count can't reach 0 without first
- // destroying all delegates with attached objects.
- *static_cast<QMetaObject *>(this) = *metaObject;
-}
-
-QQuickVisualDataModelAttachedMetaObject::~QQuickVisualDataModelAttachedMetaObject()
-{
- ::free(metaObject);
-}
-
-void QQuickVisualDataModelAttachedMetaObject::objectDestroyed(QObject *)
-{
- release();
-}
-
-int QQuickVisualDataModelAttachedMetaObject::metaCall(QObject *object, QMetaObject::Call call, int _id, void **arguments)
-{
- QQuickVisualDataModelAttached *attached = static_cast<QQuickVisualDataModelAttached *>(object);
- if (call == QMetaObject::ReadProperty) {
- if (_id >= indexPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
- *static_cast<int *>(arguments[0]) = attached->m_currentIndex[group];
- return -1;
- } else if (_id >= memberPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- *static_cast<bool *>(arguments[0]) = attached->m_cacheItem->groups & (1 << group);
- return -1;
- }
- } else if (call == QMetaObject::WriteProperty) {
- if (_id >= memberPropertyOffset) {
- if (!metaType->model)
- return -1;
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(metaType->model);
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- const int groupFlag = 1 << group;
- const bool member = attached->m_cacheItem->groups & groupFlag;
- if (member && !*static_cast<bool *>(arguments[0])) {
- Compositor::iterator it = model->m_compositor.find(
- group, attached->m_currentIndex[group]);
- model->removeGroups(it, 1, group, groupFlag);
- } else if (!member && *static_cast<bool *>(arguments[0])) {
- for (int i = 1; i < metaType->groupCount; ++i) {
- if (attached->m_cacheItem->groups & (1 << i)) {
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Group(i), attached->m_currentIndex[i]);
- model->addGroups(it, 1, Compositor::Group(i), groupFlag);
- break;
- }
- }
- }
- return -1;
- }
- }
- return attached->qt_metacall(call, _id, arguments);
-}
-
-QQuickVisualDataModelAttached::QQuickVisualDataModelAttached(QObject *parent)
- : m_cacheItem(0)
- , m_previousGroups(0)
-{
- QQml_setParent_noEvent(this, parent);
-}
-
-QQuickVisualDataModelAttached::QQuickVisualDataModelAttached(
- QQuickVisualDataModelItem *cacheItem, QObject *parent)
- : m_cacheItem(cacheItem)
- , m_previousGroups(cacheItem->groups)
-{
- QQml_setParent_noEvent(this, parent);
- if (QVDMIncubationTask *incubationTask = m_cacheItem->incubationTask) {
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i)
- m_currentIndex[i] = m_previousIndex[i] = incubationTask->index[i];
- } else {
- QQuickVisualDataModelPrivate * const model = QQuickVisualDataModelPrivate::get(m_cacheItem->metaType->model);
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i)
- m_currentIndex[i] = m_previousIndex[i] = it.index[i];
- }
-
- if (!cacheItem->metaType->metaObject)
- cacheItem->metaType->initializeMetaObject();
-
- QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject;
- cacheItem->metaType->metaObject->addref();
-}
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualDataModel::model
-
- This attached property holds the visual data model this delegate instance belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QQuickVisualDataModel *QQuickVisualDataModelAttached::model() const
-{
- return m_cacheItem ? m_cacheItem->metaType->model : 0;
-}
-
-/*!
- \qmlattachedproperty stringlist QtQuick2::VisualDataModel::groups
-
- This attached property holds the name of VisualDataGroups the item belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QStringList QQuickVisualDataModelAttached::groups() const
-{
- QStringList groups;
-
- if (!m_cacheItem)
- return groups;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_cacheItem->groups & (1 << i))
- groups.append(m_cacheItem->metaType->groupNames.at(i - 1));
- }
- return groups;
-}
-
-void QQuickVisualDataModelAttached::setGroups(const QStringList &groups)
-{
- if (!m_cacheItem)
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_cacheItem->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
- const int cacheIndex = model->m_cache.indexOf(m_cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
-}
-
-/*!
- \qmlattachedproperty bool QtQuick2::VisualDataModel::isUnresolved
-
- This attached property holds whether the visual item is bound to a data model index.
- Returns true if the item is not bound to the model, and false if it is.
-
- An unresolved item can be bound to the data model using the VisualDataGroup::resolve()
- function.
-
- It is attached to each instance of the delegate.
-*/
-
-bool QQuickVisualDataModelAttached::isUnresolved() const
-{
- if (!m_cacheItem)
- return false;
-
- return m_cacheItem->groups & Compositor::UnresolvedFlag;
-}
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualDataModel::inItems
-
- This attached property holds whether the item belongs to the default \l items VisualDataGroup.
-
- Changing this property will add or remove the item from the items group.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualDataModel::itemsIndex
-
- This attached property holds the index of the item in the default \l items VisualDataGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualDataModel::inPersistedItems
-
- This attached property holds whether the item belongs to the \l persistedItems VisualDataGroup.
-
- Changing this property will add or remove the item from the items group. Change with caution
- as removing an item from the persistedItems group will destroy the current instance if it is
- not referenced by a model.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualDataModel::persistedItemsIndex
-
- This attached property holds the index of the item in the \l persistedItems VisualDataGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-void QQuickVisualDataModelAttached::emitChanges()
-{
- const int groupChanges = m_previousGroups ^ m_cacheItem->groups;
- m_previousGroups = m_cacheItem->groups;
-
- int indexChanges = 0;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_previousIndex[i] != m_currentIndex[i]) {
- m_previousIndex[i] = m_currentIndex[i];
- indexChanges |= (1 << i);
- }
- }
-
- int notifierId = 0;
- const QMetaObject *meta = metaObject();
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (groupChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, 0);
- }
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (indexChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, 0);
- }
-
- if (groupChanges)
- emit groupsChanged();
-}
-
-//============================================================================
-
-void QQuickVisualDataGroupPrivate::setModel(QQuickVisualDataModel *m, Compositor::Group g)
-{
- Q_ASSERT(!model);
- model = m;
- group = g;
-}
-
-bool QQuickVisualDataGroupPrivate::isChangedConnected()
-{
- Q_Q(QQuickVisualDataGroup);
- IS_SIGNAL_CONNECTED(q, QQuickVisualDataGroup, changed, (const QQmlV8Handle &,const QQmlV8Handle &));
-}
-
-void QQuickVisualDataGroupPrivate::emitChanges(QV8Engine *engine)
-{
- Q_Q(QQuickVisualDataGroup);
- if (isChangedConnected() && !changeSet.isEmpty()) {
- v8::HandleScope handleScope;
- v8::Context::Scope contextScope(engine->context());
- v8::Local<v8::Object> removed = engineData(engine)->array(engine, changeSet.removes());
- v8::Local<v8::Object> inserted = engineData(engine)->array(engine, changeSet.inserts());
- emit q->changed(QQmlV8Handle::fromHandle(removed), QQmlV8Handle::fromHandle(inserted));
- }
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQuickVisualDataGroupPrivate::emitModelUpdated(bool reset)
-{
- for (QQuickVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->emitModelUpdated(changeSet, reset);
- changeSet.clear();
-}
-
-void QQuickVisualDataGroupPrivate::createdPackage(int index, QQuickPackage *package)
-{
- for (QQuickVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->createdPackage(index, package);
-}
-
-void QQuickVisualDataGroupPrivate::initPackage(int index, QQuickPackage *package)
-{
- for (QQuickVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->initPackage(index, package);
-}
-
-void QQuickVisualDataGroupPrivate::destroyingPackage(QQuickPackage *package)
-{
- for (QQuickVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->destroyingPackage(package);
-}
-
-/*!
- \qmltype VisualDataGroup
- \instantiates QQuickVisualDataGroup
- \inqmlmodule QtQuick 2
- \ingroup qtquick-models
- \brief Encapsulates a filtered set of visual data items
-
- The VisualDataGroup type provides a means to address the model data of a VisualDataModel's
- delegate items, as well as sort and filter these delegate items.
-
- The initial set of instantiable delegate items in a VisualDataModel is represented
- by its \l {QtQuick2::VisualDataModel::items}{items} group, which normally directly reflects
- the contents of the model assigned to VisualDataModel::model. This set can be changed to
- the contents of any other member of VisualDataModel::groups by assigning the \l name of that
- VisualDataGroup to the VisualDataModel::filterOnGroup property.
-
- The data of an item in a VisualDataGroup can be accessed using the get() function, which returns
- information about group membership and indexes as well as model data. In combination
- with the move() function this can be used to implement view sorting, with remove() to filter
- items out of a view, or with setGroups() and \l Package delegates to categorize items into
- different views.
-
- Data from models can be supplemented by inserting data directly into a VisualDataGroup
- with the insert() function. This can be used to introduce mock items into a view, or
- placeholder items that are later \l {resolve()}{resolved} to real model data when it becomes
- available.
-
- Delegate items can also be be instantiated directly from a VisualDataGroup using the
- create() function, making it possible to use VisualDataModel without an accompanying view
- type or to cherry-pick specific items that should be instantiated irregardless of whether
- they're currently within a view's visible area.
-
- \sa {QML Dynamic View Ordering Tutorial}
-*/
-
-QQuickVisualDataGroup::QQuickVisualDataGroup(QObject *parent)
- : QObject(*new QQuickVisualDataGroupPrivate, parent)
-{
-}
-
-QQuickVisualDataGroup::QQuickVisualDataGroup(
- const QString &name, QQuickVisualDataModel *model, int index, QObject *parent)
- : QObject(*new QQuickVisualDataGroupPrivate, parent)
-{
- Q_D(QQuickVisualDataGroup);
- d->name = name;
- d->setModel(model, Compositor::Group(index));
-}
-
-QQuickVisualDataGroup::~QQuickVisualDataGroup()
-{
-}
-
-/*!
- \qmlproperty string QtQuick2::VisualDataGroup::name
-
- This property holds the name of the group.
-
- Each group in a model must have a unique name starting with a lower case letter.
-*/
-
-QString QQuickVisualDataGroup::name() const
-{
- Q_D(const QQuickVisualDataGroup);
- return d->name;
-}
-
-void QQuickVisualDataGroup::setName(const QString &name)
-{
- Q_D(QQuickVisualDataGroup);
- if (d->model)
- return;
- if (d->name != name) {
- d->name = name;
- emit nameChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQuick2::VisualDataGroup::count
-
- This property holds the number of items in the group.
-*/
-
-int QQuickVisualDataGroup::count() const
-{
- Q_D(const QQuickVisualDataGroup);
- if (!d->model)
- return 0;
- return QQuickVisualDataModelPrivate::get(d->model)->m_compositor.count(d->group);
-}
-
-/*!
- \qmlproperty bool QtQuick2::VisualDataGroup::includeByDefault
-
- This property holds whether new items are assigned to this group by default.
-*/
-
-bool QQuickVisualDataGroup::defaultInclude() const
-{
- Q_D(const QQuickVisualDataGroup);
- return d->defaultInclude;
-}
-
-void QQuickVisualDataGroup::setDefaultInclude(bool include)
-{
- Q_D(QQuickVisualDataGroup);
- if (d->defaultInclude != include) {
- d->defaultInclude = include;
-
- if (d->model) {
- if (include)
- QQuickVisualDataModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
- else
- QQuickVisualDataModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
- }
- emit defaultIncludeChanged();
- }
-}
-
-/*!
- \qmlmethod object QtQuick2::VisualDataGroup::get(int index)
-
- Returns a javascript object describing the item at \a index in the group.
-
- The returned object contains the same information that is available to a delegate from the
- VisualDataModel attached as well as the model for that item. It has the properties:
-
- \list
- \li \b model The model data of the item. This is the same as the model context property in
- a delegate
- \li \b groups A list the of names of groups the item is a member of. This property can be
- written to change the item's membership.
- \li \b inItems Whether the item belongs to the \l {QtQuick2::VisualDataModel::items}{items} group.
- Writing to this property will add or remove the item from the group.
- \li \b itemsIndex The index of the item within the \l {QtQuick2::VisualDataModel::items}{items} group.
- \li \b {in<GroupName>} Whether the item belongs to the dynamic group \e groupName. Writing to
- this property will add or remove the item from the group.
- \li \b {<groupName>Index} The index of the item within the dynamic group \e groupName.
- \li \b isUnresolved Whether the item is bound to an index in the model assigned to
- VisualDataModel::model. Returns true if the item is not bound to the model, and false if it is.
- \endlist
-*/
-
-QQmlV8Handle QQuickVisualDataGroup::get(int index)
-{
- Q_D(QQuickVisualDataGroup);
- if (!d->model)
- return QQmlV8Handle::fromHandle(v8::Undefined());;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
- if (!model->m_context->isValid()) {
- return QQmlV8Handle::fromHandle(v8::Undefined());
- } else if (index < 0 || index >= model->m_compositor.count(d->group)) {
- qmlInfo(this) << tr("get: index out of range");
- return QQmlV8Handle::fromHandle(v8::Undefined());
- }
-
- Compositor::iterator it = model->m_compositor.find(d->group, index);
- QQuickVisualDataModelItem *cacheItem = it->inCache()
- ? model->m_cache.at(it.cacheIndex)
- : 0;
-
- if (!cacheItem) {
- cacheItem = model->m_adaptorModel.createItem(
- model->m_cacheMetaType, model->m_context->engine(), it.modelIndex());
- if (!cacheItem)
- return QQmlV8Handle::fromHandle(v8::Undefined());
- cacheItem->groups = it->flags;
-
- model->m_cache.insert(it.cacheIndex, cacheItem);
- model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- }
-
- if (model->m_cacheMetaType->constructor.IsEmpty())
- model->m_cacheMetaType->initializeConstructor();
- v8::Local<v8::Object> handle = model->m_cacheMetaType->constructor->NewInstance();
- handle->SetExternalResource(cacheItem);
- ++cacheItem->scriptRef;
-
- return QQmlV8Handle::fromHandle(handle);
-}
-
-bool QQuickVisualDataGroupPrivate::parseIndex(
- const v8::Local<v8::Value> &value, int *index, Compositor::Group *group) const
-{
- if (value->IsInt32()) {
- *index = value->Int32Value();
- return true;
- } else if (value->IsObject()) {
- v8::Local<v8::Object> object = value->ToObject();
- QQuickVisualDataModelItem * const cacheItem = v8_resource_cast<QQuickVisualDataModelItem>(object);
- if (QQuickVisualDataModelPrivate *model = cacheItem && cacheItem->metaType->model
- ? QQuickVisualDataModelPrivate::get(cacheItem->metaType->model)
- : 0) {
- *index = model->m_cache.indexOf(cacheItem);
- *group = Compositor::Cache;
- return true;
- }
- }
- return false;
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::insert(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQuick2::VisualDataGroup::insert(jsdict data, var groups = undefined)
-
- Creates a new entry at \a index in a VisualDataModel with the values from \a data that
- correspond to roles in the model assigned to VisualDataModel::model.
-
- If no index is supplied the data is appended to the model.
-
- The optional \a groups parameter identifies the groups the new entry should belong to,
- if unspecified this is equal to the group insert was called on.
-
- Data inserted into a VisualDataModel can later be merged with an existing entry in
- VisualDataModel::model using the \l resolve() function. This can be used to create placeholder
- items that are later replaced by actual data.
-*/
-
-void QQuickVisualDataGroup::insert(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- if (args->Length() == 0)
- return;
-
- int i = 0;
- v8::Local<v8::Value> v = (*args)[i];
- if (d->parseIndex(v, &index, &group)) {
- if (index < 0 || index > model->m_compositor.count(group)) {
- qmlInfo(this) << tr("insert: index out of range");
- return;
- }
- if (++i == args->Length())
- return;
- v = (*args)[i];
- }
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- int groups = 1 << d->group;
- if (++i < args->Length())
- groups |= model->m_cacheMetaType->parseGroups((*args)[i]);
-
- if (v->IsArray()) {
- return;
- } else if (v->IsObject()) {
- model->insert(before, v->ToObject(), groups);
- model->emitChanges();
- }
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::create(int index)
- \qmlmethod QtQuick2::VisualDataGroup::create(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQuick2::VisualDataGroup::create(jsdict data, array groups = undefined)
-
- Returns a reference to the instantiated item at \a index in the group.
-
- If a \a data object is provided it will be \l {insert}{inserted} at \a index and an item
- referencing this new entry will be returned. The optional \a groups parameter identifies
- the groups the new entry should belong to, if unspecified this is equal to the group create()
- was called on.
-
- All items returned by create are added to the
- \l {QtQuick2::VisualDataModel::persistedItems}{persistedItems} group. Items in this
- group remain instantiated when not referenced by any view.
-*/
-
-void QQuickVisualDataGroup::create(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- if (!d->model)
- return;
-
- if (args->Length() == 0)
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- int i = 0;
- v8::Local<v8::Value> v = (*args)[i];
- if (d->parseIndex(v, &index, &group))
- ++i;
-
- if (i < args->Length() && index >= 0 && index <= model->m_compositor.count(group)) {
- v = (*args)[i];
- if (v->IsObject()) {
- int groups = 1 << d->group;
- if (++i < args->Length())
- groups |= model->m_cacheMetaType->parseGroups((*args)[i]);
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- index = before.index[d->group];
- group = d->group;
-
- if (!model->insert(before, v->ToObject(), groups)) {
- return;
- }
- }
- }
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("create: index out of range");
- return;
- }
-
- QObject *object = model->object(group, index, false);
- if (object) {
- QVector<Compositor::Insert> inserts;
- Compositor::iterator it = model->m_compositor.find(group, index);
- model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
- model->itemsInserted(inserts);
- model->m_cache.at(it.cacheIndex)->releaseObject();
- }
-
- args->returnValue(args->engine()->newQObject(object));
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::resolve(int from, int to)
-
- Binds an unresolved item at \a from to an item in VisualDataModel::model at index \a to.
-
- Unresolved items are entries whose data has been \l {insert()}{inserted} into a VisualDataGroup
- instead of being derived from a VisualDataModel::model index. Resolving an item will replace
- the item at the target index with the unresolved item. A resolved an item will reflect the data
- of the source model at its bound index and will move when that index moves like any other item.
-
- If a new item is replaced in the VisualDataGroup onChanged() handler its insertion and
- replacement will be communicated to views as an atomic operation, creating the appearance
- that the model contents have not changed, or if the unresolved and model item are not adjacent
- that the previously unresolved item has simply moved.
-
-*/
-void QQuickVisualDataGroup::resolve(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- if (!d->model)
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
-
- if (args->Length() < 2)
- return;
-
- int from = -1;
- int to = -1;
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
-
- v8::Local<v8::Value> v = (*args)[0];
- if (d->parseIndex(v, &from, &fromGroup)) {
- if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
- qmlInfo(this) << tr("resolve: from index out of range");
- return;
- }
- } else {
- qmlInfo(this) << tr("resolve: from index invalid");
- return;
- }
-
- v = (*args)[1];
- if (d->parseIndex(v, &to, &toGroup)) {
- if (to < 0 || to >= model->m_compositor.count(toGroup)) {
- qmlInfo(this) << tr("resolve: to index out of range");
- return;
- }
- } else {
- qmlInfo(this) << tr("resolve: to index invalid");
- return;
- }
-
- Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
- Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
-
- if (!fromIt->isUnresolved()) {
- qmlInfo(this) << tr("resolve: from is not an unresolved item");
- return;
- }
- if (!toIt->list) {
- qmlInfo(this) << tr("resolve: to is not a model item");
- return;
- }
-
- const int unresolvedFlags = fromIt->flags;
- const int resolvedFlags = toIt->flags;
- const int resolvedIndex = toIt.modelIndex();
- void * const resolvedList = toIt->list;
-
- QQuickVisualDataModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex);
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
-
- if (toIt.cacheIndex > fromIt.cacheIndex)
- toIt.decrementIndexes(1, unresolvedFlags);
- if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
- from += 1;
-
- model->itemsMoved(
- QVector<Compositor::Remove>() << Compositor::Remove(fromIt, 1, unresolvedFlags, 0),
- QVector<Compositor::Insert>() << Compositor::Insert(toIt, 1, unresolvedFlags, 0));
- model->itemsInserted(
- QVector<Compositor::Insert>() << Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag));
- toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
- model->itemsRemoved(QVector<Compositor::Remove>() << Compositor::Remove(toIt, 1, resolvedFlags));
-
- model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
- model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
-
- if (resolvedFlags & Compositor::CacheFlag)
- model->m_compositor.insert(Compositor::Cache, toIt.cacheIndex, resolvedList, resolvedIndex, 1, Compositor::CacheFlag);
-
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
-
- if (!cacheItem->isReferenced()) {
- Q_ASSERT(toIt.cacheIndex == model->m_cache.indexOf(cacheItem));
- model->m_cache.removeAt(toIt.cacheIndex);
- model->m_compositor.clearFlags(Compositor::Cache, toIt.cacheIndex, 1, Compositor::CacheFlag);
- delete cacheItem;
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
- } else {
- cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
- if (cacheItem->attached)
- cacheItem->attached->emitUnresolvedChanged();
- }
-
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::remove(int index, int count)
-
- Removes \a count items starting at \a index from the group.
-*/
-
-void QQuickVisualDataGroup::remove(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- if (!d->model)
- return;
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
-
- if (args->Length() == 0)
- return;
-
- int i = 0;
- v8::Local<v8::Value> v = (*args)[i];
- if (!d->parseIndex(v, &index, &group)) {
- qmlInfo(this) << tr("remove: invalid index");
- return;
- }
-
- if (++i < args->Length()) {
- v = (*args)[i];
- if (v->IsInt32())
- count = v->Int32Value();
- }
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("remove: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("remove: invalid count");
- } else {
- model->removeGroups(it, count, d->group, 1 << d->group);
- }
- }
-}
-
-bool QQuickVisualDataGroupPrivate::parseGroupArgs(
- QQmlV8Function *args, Compositor::Group *group, int *index, int *count, int *groups) const
-{
- if (!model || !QQuickVisualDataModelPrivate::get(model)->m_cacheMetaType)
- return false;
-
- if (args->Length() < 2)
- return false;
-
- int i = 0;
- v8::Local<v8::Value> v = (*args)[i];
- if (!parseIndex(v, index, group))
- return false;
-
- v = (*args)[++i];
- if (v->IsInt32()) {
- *count = v->Int32Value();
-
- if (++i == args->Length())
- return false;
- v = (*args)[i];
- }
-
- *groups = QQuickVisualDataModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
-
- return true;
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::addGroups(int index, int count, stringlist groups)
-
- Adds \a count items starting at \a index to \a groups.
-*/
-
-void QQuickVisualDataGroup::addGroups(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("addGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("addGroups: invalid count");
- } else {
- model->addGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::removeGroups(int index, int count, stringlist groups)
-
- Removes \a count items starting at \a index from \a groups.
-*/
-
-void QQuickVisualDataGroup::removeGroups(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("removeGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("removeGroups: invalid count");
- } else {
- model->removeGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-void QQuickVisualDataGroup::setGroups(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("setGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("setGroups: invalid count");
- } else {
- model->setGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-/*!
- \qmlmethod QtQuick2::VisualDataGroup::move(var from, var to, int count)
-
- Moves \a count at \a from in a group \a to a new position.
-*/
-
-void QQuickVisualDataGroup::move(QQmlV8Function *args)
-{
- Q_D(QQuickVisualDataGroup);
-
- if (args->Length() < 2)
- return;
-
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
- int from = -1;
- int to = -1;
- int count = 1;
-
- if (!d->parseIndex((*args)[0], &from, &fromGroup)) {
- qmlInfo(this) << tr("move: invalid from index");
- return;
- }
-
- if (!d->parseIndex((*args)[1], &to, &toGroup)) {
- qmlInfo(this) << tr("move: invalid to index");
- return;
- }
-
- if (args->Length() > 2) {
- v8::Local<v8::Value> v = (*args)[2];
- if (v->IsInt32())
- count = v->Int32Value();
- }
-
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
-
- if (count < 0) {
- qmlInfo(this) << tr("move: invalid count");
- } else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
- qmlInfo(this) << tr("move: from index out of range");
- } else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
- qmlInfo(this) << tr("move: to index out of range");
- } else if (count > 0) {
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
- model->itemsMoved(removes, inserts);
- model->emitChanges();
- }
-
-}
-
-/*!
- \qmlsignal QtQuick2::VisualDataGroup::onChanged(array removed, array inserted)
-
- This handler is called when items have been removed from or inserted into the group.
-
- Each object in the \a removed and \a inserted arrays has two values; the \e index of the first
- item inserted or removed and a \e count of the number of consecutive items inserted or removed.
-
- Each index is adjusted for previous changes with all removed items preceding any inserted
- items.
-*/
-
-//============================================================================
-
-QQuickVisualPartsModel::QQuickVisualPartsModel(QQuickVisualDataModel *model, const QString &part, QObject *parent)
- : QQuickVisualModel(*new QObjectPrivate, parent)
- , m_model(model)
- , m_part(part)
- , m_compositorGroup(Compositor::Cache)
- , m_inheritGroup(true)
-{
- QQuickVisualDataModelPrivate *d = QQuickVisualDataModelPrivate::get(m_model);
- if (d->m_cacheMetaType) {
- QQuickVisualDataGroupPrivate::get(d->m_groups[1])->emitters.insert(this);
- m_compositorGroup = Compositor::Default;
- } else {
- d->m_pendingParts.insert(this);
- }
-}
-
-QQuickVisualPartsModel::~QQuickVisualPartsModel()
-{
-}
-
-QString QQuickVisualPartsModel::filterGroup() const
-{
- if (m_inheritGroup)
- return m_model->filterGroup();
- return m_filterGroup;
-}
-
-void QQuickVisualPartsModel::setFilterGroup(const QString &group)
-{
- if (QQuickVisualDataModelPrivate::get(m_model)->m_transaction) {
- qmlInfo(this) << tr("The group of a VisualDataModel cannot be changed within onChanged");
- return;
- }
-
- if (m_filterGroup != group || m_inheritGroup) {
- m_filterGroup = group;
- m_inheritGroup = false;
- updateFilterGroup();
-
- emit filterGroupChanged();
- }
-}
-
-void QQuickVisualPartsModel::resetFilterGroup()
-{
- if (!m_inheritGroup) {
- m_inheritGroup = true;
- updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQuickVisualPartsModel::updateFilterGroup()
-{
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_model);
- if (!model->m_cacheMetaType)
- return;
-
- if (m_inheritGroup) {
- if (m_filterGroup == model->m_filterGroup)
- return;
- m_filterGroup = model->m_filterGroup;
- }
-
- QQuickListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- QQuickVisualDataGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(this);
- for (int i = 1; i < model->m_groupCount; ++i) {
- if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQuickVisualDataGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQuickChangeSet::Remove> removes;
- QVector<QQuickChangeSet::Insert> inserts;
- model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQuickChangeSet changeSet;
- changeSet.move(removes, inserts);
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
- }
-}
-
-void QQuickVisualPartsModel::updateFilterGroup(
- Compositor::Group group, const QQuickChangeSet &changeSet)
-{
- if (!m_inheritGroup)
- return;
-
- m_compositorGroup = group;
- QQuickVisualDataGroupPrivate::get(QQuickVisualDataModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(this);
-
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
-
- emit filterGroupChanged();
-}
-
-int QQuickVisualPartsModel::count() const
-{
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_model);
- return model->m_delegate
- ? model->m_compositor.count(m_compositorGroup)
- : 0;
-}
-
-bool QQuickVisualPartsModel::isValid() const
-{
- return m_model->isValid();
-}
-
-QQuickItem *QQuickVisualPartsModel::item(int index, bool asynchronous)
-{
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_model);
-
- if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
- qWarning() << "VisualDataModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
- return 0;
- }
-
- QObject *object = model->object(m_compositorGroup, index, asynchronous);
-
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
- QObject *part = package->part(m_part);
- if (!part)
- return 0;
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(part)) {
- m_packaged.insertMulti(item, package);
- return item;
- }
- }
-
- model->release(object);
- if (!model->m_delegateValidated) {
- if (object)
- qmlInfo(model->m_delegate) << tr("Delegate component must be Package type.");
- model->m_delegateValidated = true;
- }
-
- return 0;
-}
-
-QQuickVisualModel::ReleaseFlags QQuickVisualPartsModel::release(QQuickItem *item)
-{
- QQuickVisualModel::ReleaseFlags flags = 0;
-
- QHash<QObject *, QQuickPackage *>::iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- QQuickPackage *package = *it;
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_model);
- flags = model->release(package);
- m_packaged.erase(it);
- if (!m_packaged.contains(item))
- flags &= ~Referenced;
- if (flags & Destroyed)
- QQuickVisualDataModelPrivate::get(m_model)->emitDestroyingPackage(package);
- }
- return flags;
-}
-
-QString QQuickVisualPartsModel::stringValue(int index, const QString &role)
-{
- return QQuickVisualDataModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
-}
-
-void QQuickVisualPartsModel::setWatchedRoles(QList<QByteArray> roles)
-{
- QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(m_model);
- model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
- m_watchedRoles = roles;
-}
-
-int QQuickVisualPartsModel::indexOf(QQuickItem *item, QObject *) const
-{
- QHash<QObject *, QQuickPackage *>::const_iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- if (QQuickVisualDataModelItem *cacheItem = QQuickVisualDataModelItem::dataForObject(*it))
- return cacheItem->groupIndex(m_compositorGroup);
- }
- return -1;
-}
-
-void QQuickVisualPartsModel::createdPackage(int index, QQuickPackage *package)
-{
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part)))
- emit createdItem(index, item);
-}
-
-void QQuickVisualPartsModel::initPackage(int index, QQuickPackage *package)
-{
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part)))
- emit initItem(index, item);
-}
-
-void QQuickVisualPartsModel::destroyingPackage(QQuickPackage *package)
-{
- if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part))) {
- Q_ASSERT(!m_packaged.contains(item));
- emit destroyingItem(item);
- item->setParentItem(0);
- }
-}
-
-void QQuickVisualPartsModel::emitModelUpdated(const QQuickChangeSet &changeSet, bool reset)
-{
- emit modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit countChanged();
-}
-
-//============================================================================
-
-v8::Handle<v8::Value> get_change_index(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- return info.This()->GetInternalField(0);
-}
-
-v8::Handle<v8::Value> get_change_count(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- return info.This()->GetInternalField(1);
-}
-
-v8::Handle<v8::Value> get_change_moveId(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- return info.This()->GetInternalField(2);
-}
-
-class QQuickVisualDataGroupChangeArray : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(ChangeSetArrayType)
-public:
- QQuickVisualDataGroupChangeArray(QV8Engine *engine)
- : QV8ObjectResource(engine)
- {
- }
-
- virtual quint32 count() const = 0;
- virtual const QQuickChangeSet::Change &at(int index) const = 0;
-
- static v8::Handle<v8::Value> get_change(quint32 index, const v8::AccessorInfo &info)
- {
- QQuickVisualDataGroupChangeArray *array = v8_resource_cast<QQuickVisualDataGroupChangeArray>(info.This());
- V8ASSERT_TYPE(array, "Not a valid change array");
-
- if (index >= array->count())
- return v8::Undefined();
-
- const QQuickChangeSet::Change &change = array->at(index);
-
- v8::Local<v8::Object> object = engineData(array->engine)->constructorChange->NewInstance();
- object->SetInternalField(0, v8::Int32::New(change.index));
- object->SetInternalField(1, v8::Int32::New(change.count));
- if (change.isMove())
- object->SetInternalField(2, v8::Int32::New(change.moveId));
-
- return object;
- }
-
- static v8::Handle<v8::Value> get_length(v8::Local<v8::String>, const v8::AccessorInfo &info)
- {
- QQuickVisualDataGroupChangeArray *array = v8_resource_cast<QQuickVisualDataGroupChangeArray>(info.This());
- V8ASSERT_TYPE(array, "Not a valid change array");
-
- return v8::Integer::New(array->count());
- }
-
- static v8::Local<v8::Function> constructor()
- {
- v8::Local<v8::FunctionTemplate> changeArray = v8::FunctionTemplate::New();
- changeArray->InstanceTemplate()->SetHasExternalResource(true);
- changeArray->InstanceTemplate()->SetIndexedPropertyHandler(get_change);
- changeArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), get_length);
- return changeArray->GetFunction();
- }
-};
-
-class QQuickVisualDataGroupRemoveArray : public QQuickVisualDataGroupChangeArray
-{
-public:
- QQuickVisualDataGroupRemoveArray(QV8Engine *engine, const QVector<QQuickChangeSet::Remove> &changes)
- : QQuickVisualDataGroupChangeArray(engine)
- , changes(changes)
- {
- }
-
- quint32 count() const { return changes.count(); }
- const QQuickChangeSet::Change &at(int index) const { return changes.at(index); }
-
-private:
- QVector<QQuickChangeSet::Remove> changes;
-};
-
-class QQuickVisualDataGroupInsertArray : public QQuickVisualDataGroupChangeArray
-{
-public:
- QQuickVisualDataGroupInsertArray(QV8Engine *engine, const QVector<QQuickChangeSet::Insert> &changes)
- : QQuickVisualDataGroupChangeArray(engine)
- , changes(changes)
- {
- }
-
- quint32 count() const { return changes.count(); }
- const QQuickChangeSet::Change &at(int index) const { return changes.at(index); }
-
-private:
- QVector<QQuickChangeSet::Insert> changes;
-};
-
-QQuickVisualDataModelEngineData::QQuickVisualDataModelEngineData(QV8Engine *)
-{
- strings = qPersistentNew(v8::Array::New(StringCount));
- strings->Set(Model, v8::String::New("model"));
- strings->Set(Groups, v8::String::New("groups"));
- strings->Set(IsUnresolved, v8::String::New("isUnresolved"));
- strings->Set(ItemsIndex, v8::String::New("itemsIndex"));
- strings->Set(PersistedItemsIndex, v8::String::New("persistedItemsIndex"));
- strings->Set(InItems, v8::String::New("inItems"));
- strings->Set(InPersistedItems, v8::String::New("inPersistedItems"));
-
- v8::Local<v8::FunctionTemplate> change = v8::FunctionTemplate::New();
- change->InstanceTemplate()->SetAccessor(v8::String::New("index"), get_change_index);
- change->InstanceTemplate()->SetAccessor(v8::String::New("count"), get_change_count);
- change->InstanceTemplate()->SetAccessor(v8::String::New("moveId"), get_change_moveId);
- change->InstanceTemplate()->SetInternalFieldCount(3);
- constructorChange = qPersistentNew(change->GetFunction());
- constructorChangeArray = qPersistentNew(QQuickVisualDataGroupChangeArray::constructor());
-}
-
-QQuickVisualDataModelEngineData::~QQuickVisualDataModelEngineData()
-{
- qPersistentDispose(strings);
- qPersistentDispose(constructorChange);
- qPersistentDispose(constructorChangeArray);
-}
-
-v8::Local<v8::Object> QQuickVisualDataModelEngineData::array(
- QV8Engine *engine, const QVector<QQuickChangeSet::Remove> &changes)
-{
- v8::Local<v8::Object> array = constructorChangeArray->NewInstance();
- array->SetExternalResource(new QQuickVisualDataGroupRemoveArray(engine, changes));
- return array;
-}
-
-v8::Local<v8::Object> QQuickVisualDataModelEngineData::array(
- QV8Engine *engine, const QVector<QQuickChangeSet::Insert> &changes)
-{
- v8::Local<v8::Object> array = constructorChangeArray->NewInstance();
- array->SetExternalResource(new QQuickVisualDataGroupInsertArray(engine, changes));
- return array;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/quick/items/qquickvisualdatamodel_p.h b/src/quick/items/qquickvisualdatamodel_p.h
deleted file mode 100644
index 03e06c82ac..0000000000
--- a/src/quick/items/qquickvisualdatamodel_p.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKVISUALDATAMODEL_P_H
-#define QQUICKVISUALDATAMODEL_P_H
-
-#include <private/qtquickglobal_p.h>
-#include <private/qquicklistcompositor_p.h>
-#include <private/qquickvisualitemmodel_p.h>
-
-#include <QtCore/qabstractitemmodel.h>
-#include <QtCore/qstringlist.h>
-
-#include <private/qv8engine_p.h>
-#include <private/qqmlglobal_p.h>
-
-QT_BEGIN_HEADER
-
-Q_DECLARE_METATYPE(QModelIndex)
-
-QT_BEGIN_NAMESPACE
-
-class QQuickChangeSet;
-class QQmlComponent;
-class QQuickPackage;
-class QQmlV8Function;
-class QQuickVisualDataGroup;
-class QQuickVisualDataModelAttached;
-class QQuickVisualDataModelPrivate;
-
-
-class Q_QUICK_PRIVATE_EXPORT QQuickVisualDataModel : public QQuickVisualModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickVisualDataModel)
-
- Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate)
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
- Q_PROPERTY(QQuickVisualDataGroup *items READ items CONSTANT)
- Q_PROPERTY(QQuickVisualDataGroup *persistedItems READ persistedItems CONSTANT)
- Q_PROPERTY(QQmlListProperty<QQuickVisualDataGroup> groups READ groups CONSTANT)
- Q_PROPERTY(QObject *parts READ parts CONSTANT)
- Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
- Q_INTERFACES(QQmlParserStatus)
-public:
- QQuickVisualDataModel();
- QQuickVisualDataModel(QQmlContext *, QObject *parent=0);
- virtual ~QQuickVisualDataModel();
-
- void classBegin();
- void componentComplete();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *);
-
- QVariant rootIndex() const;
- void setRootIndex(const QVariant &root);
-
- Q_INVOKABLE QVariant modelIndex(int idx) const;
- Q_INVOKABLE QVariant parentModelIndex() const;
-
- int count() const;
- bool isValid() const { return delegate() != 0; }
- QQuickItem *item(int index, bool asynchronous=false);
- ReleaseFlags release(QQuickItem *item);
- void cancel(int index);
- virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
-
- int indexOf(QQuickItem *item, QObject *objectContext) const;
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
-
- QQuickVisualDataGroup *items();
- QQuickVisualDataGroup *persistedItems();
- QQmlListProperty<QQuickVisualDataGroup> groups();
- QObject *parts();
-
- bool event(QEvent *);
-
- static QQuickVisualDataModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void filterGroupChanged();
- void defaultGroupsChanged();
- void rootIndexChanged();
-
-private Q_SLOTS:
- void _q_itemsChanged(int index, int count, const QVector<int> &roles);
- void _q_itemsInserted(int index, int count);
- void _q_itemsRemoved(int index, int count);
- void _q_itemsMoved(int from, int to, int count);
- void _q_modelReset();
- void _q_rowsInserted(const QModelIndex &,int,int);
- void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
- void _q_rowsRemoved(const QModelIndex &,int,int);
- void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
- void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &);
- void _q_layoutChanged();
-
-private:
- Q_DISABLE_COPY(QQuickVisualDataModel)
-};
-
-class QQuickVisualDataGroupPrivate;
-class Q_AUTOTEST_EXPORT QQuickVisualDataGroup : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
-public:
- QQuickVisualDataGroup(QObject *parent = 0);
- QQuickVisualDataGroup(const QString &name, QQuickVisualDataModel *model, int compositorType, QObject *parent = 0);
- ~QQuickVisualDataGroup();
-
- QString name() const;
- void setName(const QString &name);
-
- int count() const;
-
- bool defaultInclude() const;
- void setDefaultInclude(bool include);
-
- Q_INVOKABLE QQmlV8Handle get(int index);
-
-public Q_SLOTS:
- void insert(QQmlV8Function *);
- void create(QQmlV8Function *);
- void resolve(QQmlV8Function *);
- void remove(QQmlV8Function *);
- void addGroups(QQmlV8Function *);
- void removeGroups(QQmlV8Function *);
- void setGroups(QQmlV8Function *);
- void move(QQmlV8Function *);
-
-Q_SIGNALS:
- void countChanged();
- void nameChanged();
- void defaultIncludeChanged();
- void changed(const QQmlV8Handle &removed, const QQmlV8Handle &inserted);
-private:
- Q_DECLARE_PRIVATE(QQuickVisualDataGroup)
-};
-
-class QQuickVisualDataModelItem;
-class QQuickVisualDataModelAttachedMetaObject;
-class QQuickVisualDataModelAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQuickVisualDataModel *model READ model CONSTANT)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
- Q_PROPERTY(bool isUnresolved READ isUnresolved NOTIFY unresolvedChanged)
-public:
- QQuickVisualDataModelAttached(QObject *parent);
- QQuickVisualDataModelAttached(QQuickVisualDataModelItem *cacheItem, QObject *parent);
- ~QQuickVisualDataModelAttached() {}
-
- void setCacheItem(QQuickVisualDataModelItem *item);
-
- QQuickVisualDataModel *model() const;
-
- QStringList groups() const;
- void setGroups(const QStringList &groups);
-
- bool isUnresolved() const;
-
- void emitChanges();
-
- void emitUnresolvedChanged() { emit unresolvedChanged(); }
-
-Q_SIGNALS:
- void groupsChanged();
- void unresolvedChanged();
-
-public:
- QQuickVisualDataModelItem *m_cacheItem;
- int m_previousGroups;
- int m_currentIndex[QQuickListCompositor::MaximumGroupCount];
- int m_previousIndex[QQuickListCompositor::MaximumGroupCount];
-
- friend class QQuickVisualDataModelAttachedMetaObject;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickVisualDataModel)
-QML_DECLARE_TYPEINFO(QQuickVisualDataModel, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickVisualDataGroup)
-
-QT_END_HEADER
-
-#endif // QQUICKVISUALDATAMODEL_P_H
diff --git a/src/quick/items/qquickvisualdatamodel_p_p.h b/src/quick/items/qquickvisualdatamodel_p_p.h
deleted file mode 100644
index 89ecece064..0000000000
--- a/src/quick/items/qquickvisualdatamodel_p_p.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKVISUALDATAMODEL_P_P_H
-#define QQUICKVISUALDATAMODEL_P_P_H
-
-#include "qquickvisualdatamodel_p.h"
-
-#include "qquickvisualadaptormodel_p.h"
-
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlincubator.h>
-
-#include <private/qqmlopenmetaobject_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.
-//
-
-QT_BEGIN_NAMESPACE
-
-typedef QQuickListCompositor Compositor;
-
-class QQuickVisualDataModelAttachedMetaObject;
-
-class QQuickVisualDataModelItemMetaType : public QQmlRefCount
-{
-public:
- QQuickVisualDataModelItemMetaType(QV8Engine *engine, QQuickVisualDataModel *model, const QStringList &groupNames);
- ~QQuickVisualDataModelItemMetaType();
-
- void initializeMetaObject();
- void initializeConstructor();
-
- int parseGroups(const QStringList &groupNames) const;
- int parseGroups(const v8::Local<v8::Value> &groupNames) const;
-
- static void release_index(v8::Persistent<v8::Value> object, void *parameter);
- static void release_model(v8::Persistent<v8::Value> object, void *parameter);
-
- static v8::Handle<v8::Value> get_model(v8::Local<v8::String>, const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> get_groups(v8::Local<v8::String>, const v8::AccessorInfo &info);
- static void set_groups(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> get_member(v8::Local<v8::String>, const v8::AccessorInfo &info);
- static void set_member(
- v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> get_index(v8::Local<v8::String>, const v8::AccessorInfo &info);
-
- QQmlGuard<QQuickVisualDataModel> model;
- const int groupCount;
- QV8Engine * const v8Engine;
- QQuickVisualDataModelAttachedMetaObject *metaObject;
- const QStringList groupNames;
- v8::Persistent<v8::ObjectTemplate> constructor;
-};
-
-class QQuickVisualAdaptorModel;
-class QVDMIncubationTask;
-
-class QQuickVisualDataModelItem : public QObject, public QV8ObjectResource
-{
- Q_OBJECT
- Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
- Q_PROPERTY(QObject *model READ modelObject CONSTANT)
- V8_RESOURCE_TYPE(VisualDataItemType)
-public:
- QQuickVisualDataModelItem(QQuickVisualDataModelItemMetaType *metaType, int modelIndex);
- ~QQuickVisualDataModelItem();
-
- void referenceObject() { ++objectRef; }
- bool releaseObject() { return --objectRef == 0 && !(groups & Compositor::PersistedFlag); }
- bool isObjectReferenced() const { return objectRef != 0 || (groups & Compositor::PersistedFlag); }
-
- bool isReferenced() const {
- return scriptRef
- || incubationTask
- || ((groups & Compositor::UnresolvedFlag) && (groups & Compositor::GroupMask));
- }
-
- void Dispose();
-
- QObject *modelObject() { return this; }
-
- void incubateObject(
- QQmlComponent *component,
- QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext);
- void destroyObject();
-
- static QQuickVisualDataModelItem *dataForObject(QObject *object);
-
- int groupIndex(Compositor::Group group);
-
- int modelIndex() const { return index; }
- void setModelIndex(int idx) { index = idx; emit modelIndexChanged(); }
-
- virtual v8::Handle<v8::Value> get() { return engine->newQObject(this); }
-
- virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
- virtual bool resolveIndex(const QQuickVisualAdaptorModel &, int) { return false; }
-
- QQuickVisualDataModelItemMetaType * const metaType;
- QQmlContextData *contextData;
- QObject *object;
- QQuickVisualDataModelAttached *attached;
- QVDMIncubationTask *incubationTask;
- int objectRef;
- int scriptRef;
- int groups;
- int index;
-
-
-Q_SIGNALS:
- void modelIndexChanged();
-
-protected:
- void objectDestroyed(QObject *);
-};
-
-
-class QQuickVisualDataModelPrivate;
-class QVDMIncubationTask : public QQmlIncubator
-{
-public:
- QVDMIncubationTask(QQuickVisualDataModelPrivate *l, IncubationMode mode)
- : QQmlIncubator(mode)
- , incubating(0)
- , vdm(l) {}
-
- virtual void statusChanged(Status);
- virtual void setInitialState(QObject *);
-
- QQuickVisualDataModelItem *incubating;
- QQuickVisualDataModelPrivate *vdm;
- int index[QQuickListCompositor::MaximumGroupCount];
-};
-
-
-class QQuickVisualDataGroupEmitter
-{
-public:
- virtual ~QQuickVisualDataGroupEmitter() {}
- virtual void emitModelUpdated(const QQuickChangeSet &changeSet, bool reset) = 0;
- virtual void createdPackage(int, QQuickPackage *) {}
- virtual void initPackage(int, QQuickPackage *) {}
- virtual void destroyingPackage(QQuickPackage *) {}
-
- QIntrusiveListNode emitterNode;
-};
-
-typedef QIntrusiveList<QQuickVisualDataGroupEmitter, &QQuickVisualDataGroupEmitter::emitterNode> QQuickVisualDataGroupEmitterList;
-
-class QQuickVisualDataGroupPrivate : public QObjectPrivate
-{
-public:
- Q_DECLARE_PUBLIC(QQuickVisualDataGroup)
-
- QQuickVisualDataGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {}
-
- static QQuickVisualDataGroupPrivate *get(QQuickVisualDataGroup *group) {
- return static_cast<QQuickVisualDataGroupPrivate *>(QObjectPrivate::get(group)); }
-
- void setModel(QQuickVisualDataModel *model, Compositor::Group group);
- bool isChangedConnected();
- void emitChanges(QV8Engine *engine);
- void emitModelUpdated(bool reset);
-
- void createdPackage(int index, QQuickPackage *package);
- void initPackage(int index, QQuickPackage *package);
- void destroyingPackage(QQuickPackage *package);
-
- bool parseIndex(const v8::Local<v8::Value> &value, int *index, Compositor::Group *group) const;
- bool parseGroupArgs(
- QQmlV8Function *args, Compositor::Group *group, int *index, int *count, int *groups) const;
-
- Compositor::Group group;
- QQmlGuard<QQuickVisualDataModel> model;
- QQuickVisualDataGroupEmitterList emitters;
- QQuickChangeSet changeSet;
- QString name;
- bool defaultInclude;
-};
-
-class QQuickVisualDataModelParts;
-
-class QQuickVisualDataModelPrivate : public QObjectPrivate, public QQuickVisualDataGroupEmitter
-{
- Q_DECLARE_PUBLIC(QQuickVisualDataModel)
-public:
- QQuickVisualDataModelPrivate(QQmlContext *);
- ~QQuickVisualDataModelPrivate();
-
- static QQuickVisualDataModelPrivate *get(QQuickVisualDataModel *m) {
- return static_cast<QQuickVisualDataModelPrivate *>(QObjectPrivate::get(m));
- }
-
- void init();
- void connectModel(QQuickVisualAdaptorModel *model);
-
- QObject *object(Compositor::Group group, int index, bool asynchronous);
- QQuickVisualDataModel::ReleaseFlags release(QObject *object);
- QString stringValue(Compositor::Group group, int index, const QString &name);
- void emitCreatedPackage(QVDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitInitPackage(QVDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitCreatedItem(QVDMIncubationTask *incubationTask, QQuickItem *item) {
- emit q_func()->createdItem(incubationTask->index[m_compositorGroup], item); }
- void emitInitItem(QVDMIncubationTask *incubationTask, QQuickItem *item) {
- emit q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
- void emitDestroyingPackage(QQuickPackage *package);
- void emitDestroyingItem(QQuickItem *item) { emit q_func()->destroyingItem(item); }
- void removeCacheItem(QQuickVisualDataModelItem *cacheItem);
-
- void updateFilterGroup();
-
- void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
-
- void itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQuickChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQuickVisualDataModelItem *> > *movedItems = 0);
- void itemsInserted(const QVector<Compositor::Insert> &inserts);
- void itemsRemoved(
- const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQuickChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
- QHash<int, QList<QQuickVisualDataModelItem *> > *movedItems = 0);
- void itemsRemoved(const QVector<Compositor::Remove> &removes);
- void itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts);
- void itemsChanged(const QVector<Compositor::Change> &changes);
- template <typename T> static v8::Local<v8::Array> buildChangeList(const QVector<T> &changes);
- void emitChanges();
- void emitModelUpdated(const QQuickChangeSet &changeSet, bool reset);
-
- bool insert(Compositor::insert_iterator &before, const v8::Local<v8::Object> &object, int groups);
-
- static void group_append(QQmlListProperty<QQuickVisualDataGroup> *property, QQuickVisualDataGroup *group);
- static int group_count(QQmlListProperty<QQuickVisualDataGroup> *property);
- static QQuickVisualDataGroup *group_at(QQmlListProperty<QQuickVisualDataGroup> *property, int index);
-
- void releaseIncubator(QVDMIncubationTask *incubationTask);
- void incubatorStatusChanged(QVDMIncubationTask *incubationTask, QQmlIncubator::Status status);
- void setInitialState(QVDMIncubationTask *incubationTask, QObject *o);
-
- QQuickVisualAdaptorModel m_adaptorModel;
- QQuickListCompositor m_compositor;
- QQmlComponent *m_delegate;
- QQuickVisualDataModelItemMetaType *m_cacheMetaType;
- QQmlContext *m_context;
- QQuickVisualDataModelParts *m_parts;
- QQuickVisualDataGroupEmitterList m_pendingParts;
-
- QList<QQuickVisualDataModelItem *> m_cache;
- QList<QVDMIncubationTask *> m_finishedIncubating;
- QList<QByteArray> m_watchedRoles;
-
- QString m_filterGroup;
-
- int m_count;
- int m_groupCount;
-
- QQuickListCompositor::Group m_compositorGroup;
- bool m_complete : 1;
- bool m_delegateValidated : 1;
- bool m_reset : 1;
- bool m_transaction : 1;
- bool m_incubatorCleanupScheduled : 1;
-
- union {
- struct {
- QQuickVisualDataGroup *m_cacheItems;
- QQuickVisualDataGroup *m_items;
- QQuickVisualDataGroup *m_persistedItems;
- };
- QQuickVisualDataGroup *m_groups[Compositor::MaximumGroupCount];
- };
-};
-
-class QQuickVisualPartsModel : public QQuickVisualModel, public QQuickVisualDataGroupEmitter
-{
- Q_OBJECT
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
-public:
- QQuickVisualPartsModel(QQuickVisualDataModel *model, const QString &part, QObject *parent = 0);
- ~QQuickVisualPartsModel();
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
- void updateFilterGroup();
- void updateFilterGroup(Compositor::Group group, const QQuickChangeSet &changeSet);
-
- int count() const;
- bool isValid() const;
- QQuickItem *item(int index, bool asynchronous=false);
- ReleaseFlags release(QQuickItem *item);
- QString stringValue(int index, const QString &role);
- QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(QList<QByteArray> roles);
-
- int indexOf(QQuickItem *item, QObject *objectContext) const;
-
- void emitModelUpdated(const QQuickChangeSet &changeSet, bool reset);
-
- void createdPackage(int index, QQuickPackage *package);
- void initPackage(int index, QQuickPackage *package);
- void destroyingPackage(QQuickPackage *package);
-
-Q_SIGNALS:
- void filterGroupChanged();
-
-private:
- QQuickVisualDataModel *m_model;
- QHash<QObject *, QQuickPackage *> m_packaged;
- QString m_part;
- QString m_filterGroup;
- QList<QByteArray> m_watchedRoles;
- Compositor::Group m_compositorGroup;
- bool m_inheritGroup;
-};
-
-class QMetaPropertyBuilder;
-
-class QQuickVisualDataModelPartsMetaObject : public QQmlOpenMetaObject
-{
-public:
- QQuickVisualDataModelPartsMetaObject(QObject *parent)
- : QQmlOpenMetaObject(parent) {}
-
- virtual void propertyCreated(int, QMetaPropertyBuilder &);
- virtual QVariant initialValue(int);
-};
-
-class QQuickVisualDataModelParts : public QObject
-{
-Q_OBJECT
-public:
- QQuickVisualDataModelParts(QQuickVisualDataModel *parent);
-
- QQuickVisualDataModel *model;
- QList<QQuickVisualPartsModel *> models;
-};
-
-class QQuickVisualDataModelAttachedMetaObject : public QAbstractDynamicMetaObject, public QQmlRefCount
-{
-public:
- QQuickVisualDataModelAttachedMetaObject(
- QQuickVisualDataModelItemMetaType *metaType, QMetaObject *metaObject);
- ~QQuickVisualDataModelAttachedMetaObject();
-
- void objectDestroyed(QObject *);
- int metaCall(QObject *, QMetaObject::Call, int _id, void **);
-
-private:
- QQuickVisualDataModelItemMetaType * const metaType;
- QMetaObject * const metaObject;
- const int memberPropertyOffset;
- const int indexPropertyOffset;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/quick/items/qquickvisualitemmodel.cpp b/src/quick/items/qquickvisualitemmodel.cpp
deleted file mode 100644
index bdc489e2cf..0000000000
--- a/src/quick/items/qquickvisualitemmodel.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickvisualitemmodel_p.h"
-#include "qquickitem.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlengine.h>
-
-#include <private/qquickchangeset_p.h>
-#include <private/qqmlglobal_p.h>
-#include <private/qobject_p.h>
-
-#include <QtCore/qhash.h>
-#include <QtCore/qlist.h>
-
-QT_BEGIN_NAMESPACE
-
-QHash<QObject*, QQuickVisualItemModelAttached*> QQuickVisualItemModelAttached::attachedProperties;
-
-
-class QQuickVisualItemModelPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQuickVisualItemModel)
-public:
- class Item {
- public:
- Item(QQuickItem *i) : item(i), ref(0) {}
-
- void addRef() { ++ref; }
- bool deref() { return --ref == 0; }
-
- QQuickItem *item;
- int ref;
- };
-
- QQuickVisualItemModelPrivate() : QObjectPrivate() {}
-
- static void children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item) {
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.append(Item(item));
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->itemAppended();
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
- }
-
- static int children_count(QQmlListProperty<QQuickItem> *prop) {
- return static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.count();
- }
-
- static QQuickItem *children_at(QQmlListProperty<QQuickItem> *prop, int index) {
- return static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.at(index).item;
- }
-
- static void children_clear(QQmlListProperty<QQuickItem> *prop) {
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->itemCleared(static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children);
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.clear();
- static_cast<QQuickVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
- }
-
- void itemAppended() {
- Q_Q(QQuickVisualItemModel);
- QQuickVisualItemModelAttached *attached = QQuickVisualItemModelAttached::properties(children.last().item);
- attached->setIndex(children.count()-1);
- QQuickChangeSet changeSet;
- changeSet.insert(children.count() - 1, 1);
- emit q->modelUpdated(changeSet, false);
- emit q->countChanged();
- }
-
- void itemCleared(const QList<Item> &children) {
- Q_Q(QQuickVisualItemModel);
- foreach (const Item &child, children)
- emit q->destroyingItem(child.item);
- emit q->countChanged();
- }
-
- void emitChildrenChanged() {
- Q_Q(QQuickVisualItemModel);
- emit q->childrenChanged();
- }
-
- int indexOf(QQuickItem *item) const {
- for (int i = 0; i < children.count(); ++i)
- if (children.at(i).item == item)
- return i;
- return -1;
- }
-
-
- QList<Item> children;
-};
-
-
-/*!
- \qmltype VisualItemModel
- \instantiates QQuickVisualItemModel
- \inqmlmodule QtQuick 2
- \ingroup qtquick-models
- \brief Defines items to be used added to a view
-
- A VisualItemModel contains the visual items to be used in a view.
- When a VisualItemModel is used in a view, the view does not require
- a delegate since the VisualItemModel already contains the visual
- delegate (items).
-
- An item can determine its index within the
- model via the \l{VisualItemModel::index}{index} attached property.
-
- The example below places three colored rectangles in a ListView.
- \code
- import QtQuick 2.0
-
- Rectangle {
- VisualItemModel {
- id: itemModel
- Rectangle { height: 30; width: 80; color: "red" }
- Rectangle { height: 30; width: 80; color: "green" }
- Rectangle { height: 30; width: 80; color: "blue" }
- }
-
- ListView {
- anchors.fill: parent
- model: itemModel
- }
- }
- \endcode
-
- \image visualitemmodel.png
-
- \sa {quick/modelviews/visualitemmodel}{VisualItemModel example}
-*/
-QQuickVisualItemModel::QQuickVisualItemModel(QObject *parent)
- : QQuickVisualModel(*(new QQuickVisualItemModelPrivate), parent)
-{
-}
-
-/*!
- \qmlattachedproperty int QtQuick2::VisualItemModel::index
- This attached property holds the index of this delegate's item within the model.
-
- It is attached to each instance of the delegate.
-*/
-
-QQmlListProperty<QQuickItem> QQuickVisualItemModel::children()
-{
- Q_D(QQuickVisualItemModel);
- return QQmlListProperty<QQuickItem>(this,
- d,
- d->children_append,
- d->children_count,
- d->children_at,
- d->children_clear);
-}
-
-/*!
- \qmlproperty int QtQuick2::VisualItemModel::count
-
- The number of items in the model. This property is readonly.
-*/
-int QQuickVisualItemModel::count() const
-{
- Q_D(const QQuickVisualItemModel);
- return d->children.count();
-}
-
-bool QQuickVisualItemModel::isValid() const
-{
- return true;
-}
-
-QQuickItem *QQuickVisualItemModel::item(int index, bool)
-{
- Q_D(QQuickVisualItemModel);
- QQuickVisualItemModelPrivate::Item &item = d->children[index];
- item.addRef();
- if (item.ref == 1) {
- emit initItem(index, item.item);
- emit createdItem(index, item.item);
- }
- return item.item;
-}
-
-QQuickVisualModel::ReleaseFlags QQuickVisualItemModel::release(QQuickItem *item)
-{
- Q_D(QQuickVisualItemModel);
- int idx = d->indexOf(item);
- if (idx >= 0) {
- if (d->children[idx].deref()) {
- // XXX todo - the original did item->scene()->removeItem(). Why?
- item->setParentItem(0);
- } else {
- return QQuickVisualModel::Referenced;
- }
- }
- return 0;
-}
-
-QString QQuickVisualItemModel::stringValue(int index, const QString &name)
-{
- Q_D(QQuickVisualItemModel);
- if (index < 0 || index >= d->children.count())
- return QString();
- return QQmlEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
-}
-
-int QQuickVisualItemModel::indexOf(QQuickItem *item, QObject *) const
-{
- Q_D(const QQuickVisualItemModel);
- return d->indexOf(item);
-}
-
-QQuickVisualItemModelAttached *QQuickVisualItemModel::qmlAttachedProperties(QObject *obj)
-{
- return QQuickVisualItemModelAttached::properties(obj);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/quick/items/qquickvisualitemmodel_p.h b/src/quick/items/qquickvisualitemmodel_p.h
deleted file mode 100644
index a5d50f9d38..0000000000
--- a/src/quick/items/qquickvisualitemmodel_p.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKVISUALITEMMODEL_P_H
-#define QQUICKVISUALITEMMODEL_P_H
-
-#include <private/qtquickglobal_p.h>
-#include <QtQml/qqml.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QQuickItem;
-class QQuickChangeSet;
-
-class Q_QUICK_PRIVATE_EXPORT QQuickVisualModel : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-public:
- virtual ~QQuickVisualModel() {}
-
- enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
- Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
-
- virtual int count() const = 0;
- virtual bool isValid() const = 0;
- virtual QQuickItem *item(int index, bool asynchronous=false) = 0;
- virtual ReleaseFlags release(QQuickItem *item) = 0;
- virtual void cancel(int) {}
- virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
-
- virtual int indexOf(QQuickItem *item, QObject *objectContext) const = 0;
-
-Q_SIGNALS:
- void countChanged();
- void modelUpdated(const QQuickChangeSet &changeSet, bool reset);
- void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
- void destroyingItem(QQuickItem *item);
-
-protected:
- QQuickVisualModel(QObjectPrivate &dd, QObject *parent = 0)
- : QObject(dd, parent) {}
-
-private:
- Q_DISABLE_COPY(QQuickVisualModel)
-};
-
-class QQuickVisualItemModelAttached;
-class QQuickVisualItemModelPrivate;
-class Q_QUICK_PRIVATE_EXPORT QQuickVisualItemModel : public QQuickVisualModel
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickVisualItemModel)
-
- Q_PROPERTY(QQmlListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "children")
-
-public:
- QQuickVisualItemModel(QObject *parent=0);
- virtual ~QQuickVisualItemModel() {}
-
- virtual int count() const;
- virtual bool isValid() const;
- virtual QQuickItem *item(int index, bool asynchronous=false);
- virtual ReleaseFlags release(QQuickItem *item);
- virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray>) {}
-
- virtual int indexOf(QQuickItem *item, QObject *objectContext) const;
-
- QQmlListProperty<QQuickItem> children();
-
- static QQuickVisualItemModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void childrenChanged();
-
-private:
- Q_DISABLE_COPY(QQuickVisualItemModel)
-};
-
-class QQuickVisualItemModelAttached : public QObject
-{
- Q_OBJECT
-
-public:
- QQuickVisualItemModelAttached(QObject *parent)
- : QObject(parent), m_index(0) {}
- ~QQuickVisualItemModelAttached() {
- attachedProperties.remove(parent());
- }
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- int index() const { return m_index; }
- void setIndex(int idx) {
- if (m_index != idx) {
- m_index = idx;
- emit indexChanged();
- }
- }
-
- static QQuickVisualItemModelAttached *properties(QObject *obj) {
- QQuickVisualItemModelAttached *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QQuickVisualItemModelAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
- }
-
-Q_SIGNALS:
- void indexChanged();
-
-public:
- int m_index;
-
- static QHash<QObject*, QQuickVisualItemModelAttached*> attachedProperties;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickVisualModel)
-QML_DECLARE_TYPE(QQuickVisualItemModel)
-QML_DECLARE_TYPEINFO(QQuickVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-
-#endif // QQUICKVISUALITEMMODEL_P_H
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 469ea4225c..176f46e3b7 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -50,7 +50,7 @@
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qsgflashnode_p.h>
-#include <private/qquickwindowmanager_p.h>
+#include <private/qsgrenderloop_p.h>
#include <private/qguiapplication_p.h>
#include <QtGui/QInputMethod>
@@ -77,8 +77,11 @@ void QQuickWindowPrivate::updateFocusItemTransform()
Q_Q(QQuickWindow);
#ifndef QT_NO_IM
QQuickItem *focus = q->activeFocusItem();
- if (focus && qApp->focusObject() == focus)
- qApp->inputMethod()->setInputItemTransform(QQuickItemPrivate::get(focus)->itemToWindowTransform());
+ if (focus && qApp->focusObject() == focus) {
+ QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus);
+ qApp->inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform());
+ qApp->inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height));
+ }
#endif
}
@@ -221,17 +224,17 @@ void QQuickWindow::hideEvent(QHideEvent *)
}
/*! \reimp */
-void QQuickWindow::focusOutEvent(QFocusEvent *)
+void QQuickWindow::focusOutEvent(QFocusEvent *ev)
{
Q_D(QQuickWindow);
- d->contentItem->setFocus(false);
+ d->contentItem->setFocus(false, ev->reason());
}
/*! \reimp */
-void QQuickWindow::focusInEvent(QFocusEvent *)
+void QQuickWindow::focusInEvent(QFocusEvent *ev)
{
Q_D(QQuickWindow);
- d->contentItem->setFocus(true);
+ d->contentItem->setFocus(true, ev->reason());
d->updateFocusItemTransform();
}
@@ -345,6 +348,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
}
renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
+ renderer->setDevicePixelRatio(q->devicePixelRatio());
context->renderNextFrame(renderer, fboId);
emit q->afterRendering();
@@ -366,8 +370,8 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, windowManager(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
- , persistentGLContext(false)
- , persistentSceneGraph(false)
+ , persistentGLContext(true)
+ , persistentSceneGraph(true)
, lastWheelEventAccepted(false)
, renderTarget(0)
, renderTargetId(0)
@@ -392,13 +396,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
contentItemPrivate->windowRefCount = 1;
contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
- // In the absence of a focus in event on some platforms assume the window will
- // be activated immediately and set focus on the contentItem
- // ### Remove when QTBUG-22415 is resolved.
- //It is important that this call happens after the contentItem has a window..
- contentItem->setFocus(true);
-
- windowManager = QQuickWindowManager::instance();
+ windowManager = QSGRenderLoop::instance();
context = windowManager->sceneGraphContext();
q->setSurfaceType(QWindow::OpenGLSurface);
q->setFormat(context->defaultSurfaceFormat());
@@ -406,6 +404,8 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
+
+ QObject::connect(q, SIGNAL(focusObjectChanged(QObject*)), q, SIGNAL(activeFocusItemChanged()));
}
/*!
@@ -611,7 +611,12 @@ void QQuickWindowPrivate::translateTouchEvent(QTouchEvent *touchEvent)
touchEvent->setTouchPoints(touchPoints);
}
-void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+/*!
+Set the focus inside \a scope to be \a item.
+If the scope contains the active focus item, it will be changed to \a item.
+Calls notifyFocusChangesRecur for all changed items.
+*/
+void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
{
Q_Q(QQuickWindow);
@@ -630,13 +635,13 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- QQuickItem *oldActiveFocusItem = 0;
QQuickItem *newActiveFocusItem = 0;
QVarLengthArray<QQuickItem *, 20> changed;
// Does this change the active focus?
if (item == contentItem || (scopePrivate->activeFocus && item->isEnabled())) {
+ QQuickItem *oldActiveFocusItem = 0;
oldActiveFocusItem = activeFocusItem;
newActiveFocusItem = item;
while (newActiveFocusItem->isFocusScope()
@@ -651,7 +656,7 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
#endif
activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+ QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
@@ -676,10 +681,10 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
}
if (!(options & DontChangeFocusProperty)) {
-// if (item != contentItem || QGuiApplication::focusWindow() == q) { // QTBUG-22415
+ if (item != contentItem || QGuiApplication::focusWindow() == q) {
itemPrivate->focus = true;
changed << item;
-// }
+ }
}
if (newActiveFocusItem && contentItem->hasFocus()) {
@@ -696,8 +701,9 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
}
afi = afi->parentItem();
}
+ updateFocusItemTransform();
- QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+ QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}
@@ -707,7 +713,7 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
notifyFocusChangesRecur(changed.data(), changed.count() - 1);
}
-void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
{
Q_Q(QQuickWindow);
@@ -747,7 +753,7 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
#endif
activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+ QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
@@ -777,8 +783,9 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
if (newActiveFocusItem) {
Q_ASSERT(newActiveFocusItem == scope);
activeFocusItem = scope;
+ updateFocusItemTransform();
- QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+ QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}
@@ -834,11 +841,11 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
\brief Creates a new top-level window
The Window object creates a new top-level window for a QtQuick scene. It automatically sets up the
- window for use with QtQuick 2.0 graphical types.
+ window for use with QtQuick 2.x graphical types.
To use this type, you will need to import the module with the following line:
\code
- import QtQuick.Window 2.0
+ import QtQuick.Window 2.1
\endcode
Restricting this import will allow you to have a QML environment without access to window system features.
@@ -915,7 +922,7 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
scene graph and its OpenGL context being deleted. The
sceneGraphInvalidated() signal will be emitted when this happens.
- \sa {OpenGL Under QML}
+ \sa {Scene Graph - OpenGL Under QML}
*/
@@ -929,6 +936,8 @@ QQuickWindow::QQuickWindow(QWindow *parent)
d->init(this);
}
+
+
/*!
\internal
*/
@@ -972,20 +981,32 @@ QQuickWindow::~QQuickWindow()
void QQuickWindow::releaseResources()
{
Q_D(QQuickWindow);
- d->windowManager->releaseResources();
+ d->windowManager->releaseResources(this);
QQuickPixmap::purgeCache();
}
/*!
- Sets whether the OpenGL context can be released as a part of a call to
- releaseResources() to \a persistent.
+ Sets whether the OpenGL context can be released to \a
+ persistent. The default value is true.
+
+ The OpenGL context can be released to free up graphics resources
+ when the window is obscured, hidden or not rendering. When this
+ happens is implementation specific.
- The OpenGL context might still be released when the user makes an explicit
- call to hide().
+ The QOpenGLContext::aboutToBeDestroyed() signal is emitted from
+ the QQuickWindow::openglContext() when the OpenGL context is about
+ to be released. The QQuickWindow::sceneGraphInitialized() signal
+ is emitted when a new OpenGL context is created for this
+ window. Make a Qt::DirectConnection to these signals to be
+ notified.
- \sa setPersistentSceneGraph()
+ The OpenGL context is still released when the last QQuickWindow is
+ deleted.
+
+ \sa setPersistentSceneGraph(),
+ QOpenGLContext::aboutToBeDestroyed(), sceneGraphInitialized()
*/
void QQuickWindow::setPersistentOpenGLContext(bool persistent)
@@ -995,9 +1016,13 @@ void QQuickWindow::setPersistentOpenGLContext(bool persistent)
}
+
/*!
- Returns whether the OpenGL context can be released as a part of a call to
- releaseResources().
+ Returns whether the OpenGL context can be released during the
+ lifetime of the QQuickWindow.
+
+ \note This is a hint. When and how this happens is implementation
+ specific.
*/
bool QQuickWindow::isPersistentOpenGLContext() const
@@ -1009,13 +1034,24 @@ bool QQuickWindow::isPersistentOpenGLContext() const
/*!
- Sets whether the scene graph nodes and resources can be released as a
- part of a call to releaseResources() to \a persistent.
+ Sets whether the scene graph nodes and resources can be released
+ to \a persistent. The default value is true.
+
+ The scene graph nodes and resources can be released to free up
+ graphics resources when the window is obscured, hidden or not
+ rendering. When this happens is implementation specific.
+
+ The QQuickWindow::sceneGraphInvalidated() signal is emitted when
+ cleanup occurs. The QQuickWindow::sceneGraphInitialized() signal
+ is emitted when a new scene graph is recreated for this
+ window. Make a Qt::DirectConnection to these signals to be
+ notified.
- The scene graph nodes and resources might still be released when the user
- makes an explicit call to hide().
+ The scene graph nodes and resources are still released when the
+ last QQuickWindow is deleted.
- \sa setPersistentOpenGLContext()
+ \sa setPersistentOpenGLContext(),
+ sceneGraphInvalidated(), sceneGraphInitialized()
*/
void QQuickWindow::setPersistentSceneGraph(bool persistent)
@@ -1027,8 +1063,11 @@ void QQuickWindow::setPersistentSceneGraph(bool persistent)
/*!
- Returns whether the scene graph nodes and resources can be released as a part
- of a call to releaseResources().
+ Returns whether the scene graph nodes and resources can be
+ released during the lifetime of this QQuickWindow.
+
+ \note This is a hint. When and how this happens is implementation
+ specific.
*/
bool QQuickWindow::isPersistentSceneGraph() const
@@ -1161,6 +1200,12 @@ void QQuickWindow::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWindow);
+#ifndef QT_NO_SHORTCUT
+ // Try looking for a Shortcut before sending key events
+ if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focusObject(), e))
+ return;
+#endif
+
if (d->activeFocusItem)
sendEvent(d->activeFocusItem, e);
}
@@ -2783,6 +2828,14 @@ void QQuickWindow::setColor(const QColor &color)
if (color == d->clearColor)
return;
+ if (color.alpha() != d->clearColor.alpha()) {
+ QSurfaceFormat fmt = format();
+ if (color.alpha() < 255)
+ fmt.setAlphaBufferSize(8);
+ else
+ fmt.setAlphaBufferSize(-1);
+ setFormat(fmt);
+ }
d->clearColor = color;
emit colorChanged(color);
d->dirtyItem(contentItem());
@@ -2805,7 +2858,7 @@ QColor QQuickWindow::color() const
*/
/*!
- \qmlproperty string QtQuick.Window2::Window::modality
+ \qmlproperty Qt::WindowModality QtQuick.Window2::Window::modality
The modality of the window.
@@ -2814,6 +2867,135 @@ QColor QQuickWindow::color() const
and Qt.ApplicationModal.
*/
+/*!
+ \qmlproperty Qt::WindowFlags QtQuick.Window2::Window::flags
+
+ The window flags of the window.
+
+ The window flags control the window's appearance in the windowing system,
+ whether it's a dialog, popup, or a regular window, and whether it should
+ have a title bar, etc.
+
+ The flags which you read from this property might differ from the ones
+ that you set if the requested flags could not be fulfilled.
+ */
+
+/*!
+ \qmlproperty int QtQuick.Window2::Window::x
+ \qmlproperty int QtQuick.Window2::Window::y
+ \qmlproperty int QtQuick.Window2::Window::width
+ \qmlproperty int QtQuick.Window2::Window::height
+
+ Defines the window's position and size.
+
+ The (x,y) position is relative to the \l Screen if there is only one,
+ or to the virtual desktop (arrangement of multiple screens).
+
+ \qml
+ Window { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+
+ \image screen-and-window-dimensions.jpg
+ */
+
+/*!
+ \qmlproperty int QtQuick.Window2::Window::minimumWidth
+ \qmlproperty int QtQuick.Window2::Window::minimumHeight
+ \since Qt 5.1
+
+ Defines the window's minimum size.
+
+ This is a hint to the window manager to prevent resizing below the specified
+ width and height.
+ */
+
+/*!
+ \qmlproperty int QtQuick.Window2::Window::maximumWidth
+ \qmlproperty int QtQuick.Window2::Window::maximumHeight
+ \since Qt 5.1
+
+ Defines the window's maximum size.
+
+ This is a hint to the window manager to prevent resizing above the specified
+ width and height.
+ */
+
+/*!
+ \qmlproperty bool QtQuick.Window2::Window::visible
+
+ Whether the window is visible on the screen.
+
+ Setting visible to false is the same as setting \l visibility to Hidden.
+
+ \sa visibility
+ */
+
+/*!
+ \qmlproperty QWindow::Visibility QtQuick.Window2::Window::visibility
+
+ The screen-occupation state of the window.
+
+ Visibility is whether the window should appear in the windowing system as
+ normal, minimized, maximized, fullscreen or hidden.
+
+ To set the visibility to AutomaticVisibility means to give the window a
+ default visible state, which might be fullscreen or windowed depending on
+ the platform. However when reading the visibility property you will always
+ get the actual state, never AutomaticVisibility.
+
+ When a window is not visible its visibility is Hidden, and setting
+ visibility to Hidden is the same as setting \l visible to false.
+
+ \sa visible
+ \since Qt 5.1
+ */
+
+/*!
+ \qmlproperty Qt::ScreenOrientation QtQuick.Window2::Window::contentOrientation
+
+ This is a hint to the window manager in case it needs to display
+ additional content like popups, dialogs, status bars, or similar
+ in relation to the window.
+
+ The recommended orientation is \l Screen.orientation, but
+ an application doesn't have to support all possible orientations,
+ and thus can opt to ignore the current screen orientation.
+
+ The difference between the window and the content orientation
+ determines how much to rotate the content by.
+
+ The default value is Qt::PrimaryOrientation.
+
+ \sa Screen
+
+ \since Qt 5.1
+ */
+
+/*!
+ \qmlproperty real QtQuick.Window2::Window::opacity
+
+ The opacity of the window.
+
+ If the windowing system supports window opacity, this can be used to fade the
+ window in and out, or to make it semitransparent.
+
+ A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
+ is treated as fully transparent. Values inbetween represent varying levels of
+ translucency between the two extremes.
+
+ The default value is 1.0.
+
+ \since Qt 5.1
+ */
+
+/*!
+ \qmlproperty Item QtQuick.Window2::Window::activeFocusItem
+ \since Qt 5.1
+
+ The item which currently has active focus or \c null if there is
+ no item with active focus.
+ */
+
#include "moc_qquickwindow.cpp"
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index a98f3a695f..a2ba9e9fe0 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -48,8 +48,6 @@
#include <QtGui/qwindow.h>
#include <QtGui/qevent.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -66,6 +64,7 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow
Q_PRIVATE_PROPERTY(QQuickWindow::d_func(), QQmlListProperty<QObject> data READ data DESIGNABLE false)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT FINAL)
+ Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1)
Q_CLASSINFO("DefaultProperty", "data")
Q_DECLARE_PRIVATE(QQuickWindow)
public:
@@ -131,6 +130,7 @@ Q_SIGNALS:
void beforeRendering();
void afterRendering();
void colorChanged(const QColor &);
+ Q_REVISION(1) void activeFocusItemChanged();
public Q_SLOTS:
void update();
@@ -173,7 +173,5 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QQuickWindow *)
-QT_END_HEADER
-
#endif // QQUICKWINDOW_H
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index da2ae8284d..ab772ca2bc 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
//Make it easy to identify and customize the root item if needed
-class QQuickWindowManager;
+class QSGRenderLoop;
class QQuickRootItem : public QQuickItem
{
@@ -163,8 +163,8 @@ public:
};
Q_DECLARE_FLAGS(FocusOptions, FocusOption)
- void setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
- void clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
+ void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
+ void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
void updateFocusItemTransform();
@@ -200,7 +200,7 @@ public:
QSGContext *context;
QSGRenderer *renderer;
- QQuickWindowManager *windowManager;
+ QSGRenderLoop *windowManager;
QColor clearColor;
diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp
deleted file mode 100644
index 69aa63c278..0000000000
--- a/src/quick/items/qquickwindowmanager.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickwindowmanager_p.h"
-#include "qquickthreadedwindowmanager_p.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QTime>
-#include <QtCore/private/qabstractanimation_p.h>
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include <QtQml/private/qqmlglobal_p.h>
-
-#include <QtQuick/QQuickWindow>
-#include <QtQuick/private/qquickwindow_p.h>
-#include <QtQuick/private/qsgcontext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qquick_render_timing, QML_RENDER_TIMING)
-
-extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-
-/*!
- expectations for this manager to work:
- - one opengl context to render multiple windows
- - OpenGL pipeline will not block for vsync in swap
- - OpenGL pipeline will block based on a full buffer queue.
- - Multiple screens can share the OpenGL context
- - Animations are advanced for all windows once per swap
- */
-
-DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP);
-DEFINE_BOOL_CONFIG_OPTION(qmlForceThreadedRenderer, QML_FORCE_THREADED_RENDERER); // Might trigger graphics driver threading bugs, use at own risk
-
-QQuickWindowManager *QQuickWindowManager::s_instance = 0;
-
-QQuickWindowManager::~QQuickWindowManager()
-{
-}
-
-class QQuickTrivialWindowManager : public QObject, public QQuickWindowManager
-{
- Q_OBJECT
-public:
- QQuickTrivialWindowManager();
-
- void show(QQuickWindow *window);
- void hide(QQuickWindow *window);
-
- void windowDestroyed(QQuickWindow *window);
-
- void initializeGL();
- void renderWindow(QQuickWindow *window);
- void exposureChanged(QQuickWindow *window);
- QImage grab(QQuickWindow *window);
- void resize(QQuickWindow *window, const QSize &size);
-
- void maybeUpdate(QQuickWindow *window);
- void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation.
-
- void releaseResources() { }
-
- QAnimationDriver *animationDriver() const { return 0; }
-
- QSGContext *sceneGraphContext() const;
-
- bool event(QEvent *);
-
- struct WindowData {
- bool updatePending : 1;
- bool grabOnly : 1;
- };
-
- QHash<QQuickWindow *, WindowData> m_windows;
-
- QOpenGLContext *gl;
- QSGContext *sg;
-
- QImage grabContent;
-
- bool eventPending;
-};
-
-
-QQuickWindowManager *QQuickWindowManager::instance()
-{
- if (!s_instance) {
-
- s_instance = QSGContext::createWindowManager();
-
- bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
-#ifdef Q_OS_WIN
- bool fancy = false; // QTBUG-28037
-#else
- bool fancy = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL);
-#endif
- if (qmlNoThreadedRenderer())
- fancy = false;
- else if (qmlForceThreadedRenderer())
- fancy = true;
-
- // Enable fixed animation steps...
- QByteArray fixed = qgetenv("QML_FIXED_ANIMATION_STEP");
- bool fixedAnimationSteps = bufferQueuing;
- if (fixed == "no")
- fixedAnimationSteps = false;
- else if (fixed.length())
- fixedAnimationSteps = true;
- if (fixedAnimationSteps)
- QUnifiedTimer::instance(true)->setConsistentTiming(true);
-
- if (!s_instance) {
- s_instance = fancy
- ? (QQuickWindowManager*) new QQuickRenderThreadSingleContextWindowManager
- : (QQuickWindowManager*) new QQuickTrivialWindowManager;
- }
- }
- return s_instance;
-}
-
-void QQuickWindowManager::setInstance(QQuickWindowManager *instance)
-{
- Q_ASSERT(!s_instance);
- s_instance = instance;
-}
-
-QQuickTrivialWindowManager::QQuickTrivialWindowManager()
- : gl(0)
- , eventPending(false)
-{
- sg = QSGContext::createDefaultContext();
-}
-
-
-void QQuickTrivialWindowManager::show(QQuickWindow *window)
-{
- WindowData data;
- data.updatePending = false;
- data.grabOnly = false;
- m_windows[window] = data;
-
- maybeUpdate(window);
-}
-
-void QQuickTrivialWindowManager::hide(QQuickWindow *window)
-{
- if (!m_windows.contains(window))
- return;
-
- m_windows.remove(window);
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- cd->cleanupNodesOnShutdown();
-
- if (m_windows.size() == 0) {
- sg->invalidate();
- delete gl;
- gl = 0;
- }
-}
-
-void QQuickTrivialWindowManager::windowDestroyed(QQuickWindow *window)
-{
- hide(window);
-}
-
-void QQuickTrivialWindowManager::renderWindow(QQuickWindow *window)
-{
- bool renderWithoutShowing = QQuickWindowPrivate::get(window)->renderWithoutShowing;
- if ((!window->isExposed() && !renderWithoutShowing) || !m_windows.contains(window))
- return;
-
- WindowData &data = const_cast<WindowData &>(m_windows[window]);
-
- QQuickWindow *masterWindow = 0;
- if (!window->isVisible() && !renderWithoutShowing) {
- // Find a "proper surface" to bind...
- for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin();
- it != m_windows.constEnd() && !masterWindow; ++it) {
- if (it.key()->isVisible())
- masterWindow = it.key();
- }
- } else {
- masterWindow = window;
- }
-
- if (!masterWindow)
- return;
-
- if (!QQuickWindowPrivate::get(masterWindow)->isRenderable()) {
- qWarning().nospace()
- << "Unable to find a renderable master window "
- << masterWindow << "when trying to render"
- << window << " (" << window->geometry() << ").";
- return;
- }
-
- if (!gl) {
- gl = new QOpenGLContext();
- gl->setFormat(masterWindow->requestedFormat());
- gl->create();
- if (!gl->makeCurrent(masterWindow))
- qWarning("QQuickWindow: makeCurrent() failed...");
- sg->initialize(gl);
- } else {
- gl->makeCurrent(masterWindow);
- }
-
- bool alsoSwap = data.updatePending;
- data.updatePending = false;
-
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- cd->polishItems();
-
- int renderTime = 0, syncTime = 0;
- QTime renderTimer;
- if (qquick_render_timing())
- renderTimer.start();
-
- cd->syncSceneGraph();
-
- if (qquick_render_timing())
- syncTime = renderTimer.elapsed();
-
- cd->renderSceneGraph(window->size());
-
- if (qquick_render_timing())
- renderTime = renderTimer.elapsed() - syncTime;
-
- if (data.grabOnly) {
- grabContent = qt_gl_read_framebuffer(window->size(), false, false);
- data.grabOnly = false;
- }
-
- if (alsoSwap && window->isVisible()) {
- gl->swapBuffers(window);
- cd->fireFrameSwapped();
- }
-
- if (qquick_render_timing()) {
- static QTime lastFrameTime = QTime::currentTime();
- const int swapTime = renderTimer.elapsed() - renderTime - syncTime;
- qDebug() << "- Breakdown of frame time; sync:" << syncTime
- << "ms render:" << renderTime << "ms swap:" << swapTime
- << "ms total:" << swapTime + renderTime + syncTime
- << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime()))
- << "ms";
- lastFrameTime = QTime::currentTime();
- }
-
- // Might have been set during syncSceneGraph()
- if (data.updatePending)
- maybeUpdate(window);
-}
-
-void QQuickTrivialWindowManager::exposureChanged(QQuickWindow *window)
-{
- if (window->isExposed())
- maybeUpdate(window);
-}
-
-QImage QQuickTrivialWindowManager::grab(QQuickWindow *window)
-{
- if (!m_windows.contains(window))
- return QImage();
-
- m_windows[window].grabOnly = true;
-
- renderWindow(window);
-
- QImage grabbed = grabContent;
- grabContent = QImage();
- return grabbed;
-}
-
-
-
-void QQuickTrivialWindowManager::resize(QQuickWindow *, const QSize &)
-{
-}
-
-
-
-void QQuickTrivialWindowManager::maybeUpdate(QQuickWindow *window)
-{
- if (!m_windows.contains(window))
- return;
-
- m_windows[window].updatePending = true;
-
- if (!eventPending) {
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- eventPending = true;
- }
-}
-
-
-
-QSGContext *QQuickTrivialWindowManager::sceneGraphContext() const
-{
- return sg;
-}
-
-
-bool QQuickTrivialWindowManager::event(QEvent *e)
-{
- if (e->type() == QEvent::User) {
- eventPending = false;
- for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin();
- it != m_windows.constEnd(); ++it) {
- const WindowData &data = it.value();
- if (data.updatePending)
- renderWindow(it.key());
- }
- return true;
- }
- return QObject::event(e);
-}
-
-#include "qquickwindowmanager.moc"
-
-QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 8d2d583607..f826a53a29 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -50,6 +50,8 @@ void QQuickWindowModule::defineModule()
const char uri[] = "QtQuick.Window";
qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window");
+ qmlRegisterRevision<QWindow,1>(uri, 2, 1);
+ qmlRegisterType<QQuickWindow,1>(uri, 2, 1, "Window");
qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property."));
}
diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h
index 10f0c630b9..4afc45751f 100644
--- a/src/quick/items/qquickwindowmodule_p.h
+++ b/src/quick/items/qquickwindowmodule_p.h
@@ -44,8 +44,6 @@
#include <private/qtquickglobal_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -57,6 +55,4 @@ public:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif